如何用脚本自动运行Docker容器?从入门到生产级自动化部署
目录导读
为什么需要用脚本自动运行Docker容器?
在开发或运维场景中,手动输入 docker run 命令虽然简单,但存在明显痛点:

- 每次启动需记忆大量参数(端口映射、卷挂载、环境变量)
- 容器意外退出后无法自动恢复
- 批量管理多容器时效率极低
脚本化的核心价值:将容器配置固化、实现自动化启停、支持定时任务与CI/CD流水线集成,根据Docker官方最佳实践,脚本自动化是容器运维的基础能力。
基础脚本:启动、停止与重启容器
1 单容器启动脚本示例
#!/bin/bash
# start_nginx.sh - 自动运行Nginx容器
CONTAINER_NAME="my-nginx"
IMAGE="nginx:alpine"
PORT_MAP="8080:80"
# 检查容器是否已存在,存在则删除重建
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
echo "停止并删除旧容器..."
docker stop $CONTAINER_NAME
docker rm $CONTAINER_NAME
fi
# 启动新容器
docker run -d \
--name $CONTAINER_NAME \
-p $PORT_MAP \
--restart unless-stopped \
$IMAGE
echo "Nginx已启动,访问 http://localhost:8080"
关键点:
--restart unless-stopped确保容器在故障或被守护进程重启时自动恢复-d后台运行,避免占用当前终端
2 批量停止所有运行中容器
#!/bin/bash
# stop_all.sh
for container in $(docker ps -q); do
echo "停止容器: $(docker inspect --format='{{.Name}}' $container)"
docker stop $container
done
echo "所有容器已停止"
高级自动化:结合环境变量与日志记录
1 使用.env文件动态配置
#!/bin/bash
# run_with_env.sh
# 加载.env文件中的变量
export $(grep -v '^#' .env | xargs)
docker run -d \
--name app-$APP_ENV \
-e "DB_HOST=$DB_HOST" \
-e "DB_USER=$DB_USER" \
-e "DB_PASS=$DB_PASS" \
-v "$(pwd)/logs:/app/logs" \
myapp:latest
# 记录启动日志
echo "$(date): 容器启动,环境: $APP_ENV" >> docker_run.log
设计要点:
.env文件存储敏感信息(需加入.gitignore)- 日志记录便于回溯容器启动历史
2 定时拉取镜像并重建
#!/bin/bash
# auto_update.sh - 每天凌晨3点检查镜像更新
IMAGE="myapp:latest"
docker pull $IMAGE 2>&1 | grep "Image is up to date"
if [ $? -ne 0 ]; then
echo "发现新镜像,正在重建容器..."
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 3000:3000 $IMAGE
else
echo "镜像已是最新"
fi
配合crontab使用:0 3 * * * /path/to/auto_update.sh
生产级实践:健康检查与自动重启策略
1 使用Docker Compose脚本化部署
docker-compose.yml 本身就是强大的声明式脚本:
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "8080:80"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 30s
timeout: 10s
retries: 3
restart: always
通过 docker-compose up -d 即可一次启动所有服务,并自动进行健康检查。
2 自定义Shell脚本监控+重启
#!/bin/bash
# health_monitor.sh
CONTAINER="myapp"
CHECK_INTERVAL=30
while true; do
if [ "$(docker inspect -f '{{.State.Health.Status}}' $CONTAINER 2>/dev/null)" = "unhealthy" ]; then
echo "$(date): 容器健康检查失败,执行恢复..."
docker restart $CONTAINER
sleep 60 # 避免频繁重启
fi
sleep $CHECK_INTERVAL
done
优势:可定制化通知(如发送钉钉/邮件告警),比Docker自带策略更灵活。
3 CI/CD中的自动化示例(GitLab CI)
# .gitlab-ci.yml
deploy:
stage: deploy
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
- ssh deploy@server "cd /opt/app && ./deploy.sh $CI_COMMIT_SHORT_SHA"
only:
- main
deploy.sh 脚本负责拉取新镜像并更新容器。
常见FAQ:脚本运行Docker的坑与解法
Q1: 脚本中执行docker命令报“permission denied”?
A: 原因是当前用户未加入 docker 组,解决方案:
sudo usermod -aG docker $USER newgrp docker # 或重启终端
Q2: 如何让脚本在系统启动时自动运行?
A: 将脚本路径加入 /etc/rc.local 或使用systemd服务,推荐systemd方案:
[Unit] Description=Docker Container Starter After=docker.service [Service] ExecStart=/usr/local/bin/start_containers.sh Restart=on-failure [Install] WantedBy=multi-user.target
Q3: 脚本中途失败如何保证原子性?
A: 使用 set -e 在脚本开头,或使用 trap 捕获错误。
#!/bin/bash set -e trap 'echo "脚本执行失败,请检查日志"; exit 1' ERR # 你的docker命令...
Q4: 脚本中如何传递动态参数(如版本号)?
A: 通过命令行参数传入:./run.sh v1.2.3
#!/bin/bash
VERSION=${1:-latest}
docker run -d --name myapp myapp:$VERSION
Q5: 容器日志太大导致磁盘爆满?
A: 在 docker run 时添加日志限制:
docker run --log-opt max-size=10m --log-opt max-file=3 ...
或全局配置 /etc/docker/daemon.json:
{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }
用脚本自动运行Docker容器,本质是将重复、易错的命令行操作固化为可靠、可复用的自动化流程,从简单的 docker run 包装,到结合健康检查、CI/CD、定时任务的完整解决方案,脚本化能大幅提升容器运维效率,建议初学者从基础钩子脚本入手,逐步引入错误处理和日志监控,最终建立满足生产需求的自动化体系。