在使用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',等通了再启动应用,这样整个流程就自动化了。