容器开机自启动
面试题
如何让 Docker 容器在宿主机启动时自动运行?有哪些配置方式?
标准答案
容器开机自启动涉及两个层面:Docker Daemon 自启动和容器自启动。两者缺一不可。
第一步:Docker Daemon 开机自启
# 确保 Docker 服务跟随系统启动
systemctl enable docker
# 验证
systemctl is-enabled docker
# enabled
# 检查 Docker 服务的启动状态
systemctl status docker
# ● docker.service - Docker Application Container Engine
# Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
第二步:容器自启动
方法 1:–restart 策略(最常用)
# 创建容器时设置
docker run -d --restart always --name web nginx
docker run -d --restart unless-stopped --name app my-app
# 容器已经运行,更新配置
docker update --restart always my-existing-container
# 批量设置所有运行中的容器
docker update --restart unless-stopped $(docker ps -q)
# 批量设置所有容器(包括停止的)
docker update --restart always $(docker ps -aq)
不同策略对开机自启的影响
# always:Daemon 重启时自动拉回所有设置了 always 的容器
# unless-stopped:Daemon 重启时拉回,但如果是手工 stop 过的则不拉
# on-failure:只在异常退出时重启,Daemon 重启时也会拉回
# 验证开机自启效果
sudo reboot # 重启宿主机
# 重启后
docker ps # 设置了 --restart always/unless-stopped 的容器自动运行
方法 2:使用 systemd 管理容器
对于更精细的控制,可以用 systemd 来管理容器:
# 创建一个 systemd service
cat > /etc/systemd/system/my-web-app.service << 'EOF'
[Unit]
Description=My Web App Container
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a my-web-app
ExecStop=/usr/bin/docker stop -t 10 my-web-app
ExecStartPre=-/usr/bin/docker rm my-web-app
ExecStartPre=/usr/bin/docker run --name my-web-app my-app:latest
[Install]
WantedBy=multi-user.target
EOF
# 另一种更简单的方案:使用 docker run 的重启特性
cat > /etc/systemd/system/docker-container@.service << 'EOF'
[Unit]
Description=Docker Container %I
Requires=docker.service
After=docker.service
[Service]
Restart=always
ExecStart=/usr/bin/docker start -a %i
ExecStop=/usr/bin/docker stop -t 10 %i
ExecStartPre=-/usr/bin/docker rm %i
ExecStartPre=/usr/bin/docker run --name %i --restart no (此处省略完整参数)
[Install]
WantedBy=multi-user.target
EOF
方法 3:docker-compose + restart
# docker-compose.yml
version: '3'
services:
web:
image: nginx
restart: always # ← 开机自启
app:
image: my-app
restart: unless-stopped # ← 手动停过就不自启
db:
image: mysql:8
restart: always
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:alpine
restart: always # ← 开机自启
启动:
docker-compose up -d
# 宿主机重启后,这些容器会自动启动
容器启动顺序控制
# Docker 自身不保证依赖顺序
# 可以通过以下方式控制
# 方案 1:在启动脚本中等待
#!/bin/bash
# start-containers.sh
docker start db || docker run -d --name db --restart always mysql:8
# 等数据库就绪
sleep 10
docker start app || docker run -d --name app --restart always my-app
# 方案 2:docker-compose depends_on
version: '3'
services:
db:
image: mysql:8
restart: always
app:
image: my-app
restart: always
depends_on:
- db # 启动时先启动 db
# 方案 3:健康检查保证顺序
docker run -d --name db --restart always \
--health-cmd="mysqladmin ping" \
--health-interval=5s \
mysql:8
docker run -d --name app --restart always \
--health-cmd="curl -f http://localhost/health" \
--health-interval=5s \
my-app
自启动的常见问题
问题 1:容器冲突
# 同名容器冲突导致无法启动
docker run -d --restart always --name web nginx
# 重启后,如果已有同名容器(可能挂在其他设备上),新容器创建会失败
# 解决:使用 --rm 配合 restart 需要在编排中处理
问题 2:网络依赖
# 重启时网络可能还未就绪
# 解决方法:使用自定义 network-mtu 或健康检查
docker network create mynet
docker run -d --restart always --net mynet --name web nginx
问题 3:依赖顺序
# 数据库还没就绪,应用已经启动
# 解决方法:应用层做重试
# Node.js 示例
const connectWithRetry = async () => {
try {
await sequelize.authenticate();
console.log('DB connected');
} catch {
console.log('Retrying in 5s...');
setTimeout(connectWithRetry, 5000);
}
};
生产环境建议
# 1. 统一管理:用 docker-compose 管理所有需要自启的容器
# 2. 测试自启:手动重启宿主机,确认所有容器按预期启动
# 3. 监控:配置容器健康检查,自启失败时发出告警
# 4. 文档:记录哪些容器设置了自启
# 检查哪些容器设置了自启
docker ps -a --format "{{.Names}}: {{.HostConfig.RestartPolicy.Name}}" \
| grep -v "no"
# 输出示例
# web: always
# app: unless-stopped
# db: always
# redis: always
面试官追问
问:Docker Daemon 重启后,always 和 unless-stopped 的区别?
答:always:Daemon 重启后,无论容器之前什么状态,只要存在就拉起来。unless-stopped:如果容器之前被 docker stop 手动停过,Daemon 重启后不会自动启动。但如果是崩溃退出的会自启。
问:系统重启后,Docker 容器启动有顺序吗?
答:Docker Daemon 本身不保证容器启动顺序。它会尝试并发启动所有设置了自启的容器。如果需要顺序,需要使用 docker-compose 的 depends_on 或者在应用层面做重试等待。
问:CRON 定时任务中如何启动容器?
# 在 crontab 中检查并启动
*/5 * * * * docker ps | grep my-critical-app || docker start my-critical-app
总结
容器开机自启的核心配置就是 --restart always 或 --restart unless-stopped,配合 Docker 服务本身的 systemctl enable docker。建议优先使用 unless-stopped,避免运维人员手动停止容器后又被自动拉起。生产环境推荐用 docker-compose 统一管理所有容器的自启策略。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容