在日常办公自动化中,很多人会用到脚本处理重复性任务,比如批量重命名文件、定时备份数据或自动发送邮件。随着 Docker 等容器技术普及,把 Shell 脚本放到容器里运行成了一种更稳定、可移植的做法。
为什么要在容器里执行Shell脚本?
想象一下,你写了一个处理 Excel 表格的脚本,依赖特定版本的 Python 和几个库。在自己的电脑上跑得好好的,换台机器就报错。这时候,容器就派上用场了——它能把脚本和所有依赖打包在一起,像一个独立的小电脑,走到哪都能正常运行。
最简单的执行方式
假设你有一个名为 backup.sh 的脚本,内容是压缩某个目录:
#!/bin/bash
echo "开始备份..."
tar -czf /data/backup-$(date +%Y%m%d).tar.gz /data/files
echo "备份完成"
你可以基于 Alpine 镜像制作一个轻量容器来运行它:
FROM alpine:latest
COPY backup.sh /backup.sh
RUN chmod +x /backup.sh
CMD ["/backup.sh"]
构建并运行:
docker build -t my-backup .
docker run -v /host/data:/data my-backup
直接在运行中的容器执行脚本
有时候你已经有一个正在运行的容器,比如一个办公文档转换服务。想临时加个清理缓存的脚本,不用重建镜像也能搞定:
docker cp clean_cache.sh container_name:/clean_cache.sh
docker exec -it container_name /bin/sh -c 'chmod +x /clean_cache.sh && /clean_cache.sh'
脚本需要交互怎么办?
有些脚本需要用户输入确认,比如“是否继续?”这类提示。启动容器时记得加上 -it 参数,否则会因无法读取输入而失败:
docker run -it -v $(pwd)/script.sh:/script.sh ubuntu:20.04 /bin/bash -c '/script.sh'
环境变量传参更灵活
别把配置写死在脚本里。通过环境变量传递参数,能让同一个镜像在不同环境中自由切换:
docker run -e BACKUP_DIR=/data -e COMPRESS_LEVEL=9 my-backup
脚本内部用 $BACKUP_DIR 就能拿到值,部署测试和正式环境时只需改命令,不用动代码。
日志输出要清晰
脚本运行结果最好能实时看到。避免把所有输出重定向到黑洞,比如不要随便写 > /dev/null。容器的日志系统会自动捕获 stdout,用 docker logs container_name 就能查过程,排查问题省不少事。
权限问题别忽视
容器默认可能以 root 运行,但某些企业环境要求非 root 用户操作。可以在 Dockerfile 中创建普通用户:
RUN adduser -D appuser
USER appuser
确保挂载的目录对这个用户可读可写,不然脚本一执行就卡住。