容器中执行Shell脚本的实用方法

在使用Docker或其它容器技术时,经常需要让容器自动运行一些初始化操作,比如配置环境、启动服务或者批量处理文件。这时候,写一个Shell脚本并让容器执行它,是最直接的办法。

准备一个简单的Shell脚本

假设你想在容器启动时打印一句话,并创建一个日志文件,可以写一个start.sh

#!/bin/bash
echo "容器正在启动..."
mkdir -p /app/logs
echo "启动时间:$(date)" > /app/logs/start.log
exec "$@"

这个脚本做了几件事:输出提示、创建目录、记录时间,最后用exec "$@"保留传入的命令,确保容器不会立即退出。

在Dockerfile中集成脚本

把脚本复制进镜像,并设置为启动入口:

FROM alpine:latest

COPY start.sh /start.sh
RUN chmod +x /start.sh

ENTRYPOINT ["/start.sh"]
CMD ["sh"]

构建镜像后运行容器,会看到脚本自动执行。如果没加exec "$@",容器跑完脚本就停了,加了之后还能继续运行后续命令。

直接在运行时执行脚本

有时候不需要打包进镜像,可以直接挂载脚本并执行:

docker run --rm -v $(pwd)/start.sh:/tmp/start.sh alpine:latest /tmp/start.sh

这条命令把本地的start.sh挂到容器里,然后直接运行。适合调试或临时任务,比如清理缓存、备份数据。

处理权限和换行问题

常见坑点有两个:脚本没执行权限,或者Windows编辑的脚本带了\r\n换行符,导致#!/bin/bash^M报错。

解决办法:确保脚本有执行权限:chmod +x start.sh;如果是Windows写的脚本,用dos2unix start.sh转换格式,或者在Dockerfile里用sed -i 's/\r$//' /start.sh处理。

多命令场景下的做法

如果只是简单几条命令,也不一定非得写脚本。可以直接用sh -c

docker run alpine sh -c "echo 'hello'; mkdir /test; ls /"

但逻辑复杂了,还是建议写成脚本,维护起来更清楚。

实际用的时候,比如部署一个Web服务前要等数据库就绪,就可以在脚本里加循环检测mysql -h db -e 'select 1',等通了再启动应用,这样整个流程就自动化了。