6 min read

Docker 容器开机自动启动的 5 种方法,总有一款适合你!

最近有小伙伴问我,服务器重启后 Docker 容器老是得手动启动,太麻烦了,有没有什么办法能让它自动起来?这问题问得好!说实话,我也踩过这个坑,服务器一重启,服务全挂了,还得半夜起来手动启动容器,那叫一个酸爽。

今天我就把常用的几种方法都整理出来,从最简单的到企业级方案都有,大家可以根据自己的实际情况选择。废话不多说,直接上干货!

最简单的方法:使用 --restart 策略

这个方法是我个人最推荐的,真的是简单粗暴又好用。你只需要在创建容器的时候加个参数就搞定了。

如果你是新建容器,直接这样:

docker run -d --name my-container --restart always nginx

如果容器已经跑起来了,也没关系,一条命令就能补上:

docker update --restart always my-container

这里有几个重启策略可以选:

  • no:不自动重启,这是默认值(所以默认情况下容器不会自动起来)
  • on-failure[:max-retries]:只有当容器异常退出时才重启,你还能指定最多重试几次
  • always:不管啥情况都重启,除非你手动 stop 它
  • unless-stopped:这个也挺好用,自动重启但如果你手动停了就不动了

我个人最喜欢用 unless-stopped,平时自动启,我想停的时候就乖乖停着,不会在我重启服务器后又自己跑起来。

更稳定的选择:systemd 服务

如果是生产环境,我建议用 systemd 来管理,这样更规范也更可靠。虽然配置稍微复杂点,但好处是显而易见的。

首先创建一个服务文件:

sudo nano /etc/systemd/system/my-docker-container.service

然后填入这些内容:

[Unit]
Description=My Docker Container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a my-container
ExecStop=/usr/bin/docker stop -t 2 my-container

[Install]
WantedBy=multi-user.target

保存后执行这几条命令:

# 重新加载 systemd
sudo systemctl daemon-reload

# 设置开机自启
sudo systemctl enable my-docker-container.service

# 立即启动
sudo systemctl start my-docker-container.service

# 看看状态
sudo systemctl status my-docker-container.service

配置好了之后,你就可以像管理其他系统服务一样管理 Docker 容器了,是不是感觉专业了很多?

如果你用 Docker Compose

很多项目用 Docker Compose 来编排多个容器,这种情况就更简单了,直接在 yaml 文件里配置就行:

version: '3'
services:
  web:
    image: nginx:latest
    restart: always  # 或者 unless-stopped
    ports:
      - "80:80"
  
  db:
    image: postgres:13
    restart: on-failure:3  # 失败时最多重试3次
    environment:
      POSTGRES_PASSWORD: example

然后正常启动就行:

docker-compose up -d

如果还想配合 systemd(推荐),可以这样设置:

sudo systemctl enable docker-compose@your-project

备选方案:crontab

这个方法说实话不太推荐,但如果前面方法都行不通,也可以拿来应急。

crontab -e

加上这行:

@reboot sleep 5 && /usr/bin/docker start my-container

意思就是系统重启后等 5 秒再启动容器,给 Docker 服务一点启动时间。

老派方法:update-rc.d

这是 Debian/Ubuntu 系统的古老方法,现在用的人不多了,但了解一下也没坏处。

先创建启动脚本:

sudo nano /etc/init.d/docker-my-container

填入:

#!/bin/bash
case "$1" in
  start)
    docker start my-container
    ;;
  stop)
    docker stop my-container
    ;;
  *)
    echo "Usage: $0 {start|stop}"
    exit 1
    ;;
esac

然后设置权限并启用:

sudo chmod +x /etc/init.d/docker-my-container
sudo update-rc.d docker-my-container defaults

设置好了怎么验证?

设置完总得验证一下吧?可以用这个命令看看重启策略:

docker inspect my-container --format='{{.HostConfig.RestartPolicy.Name}}'

然后测试一下重启:

# 只重启 Docker 服务
sudo systemctl restart docker

# 或者直接重启整个系统
sudo reboot

# 重启后检查容器状态
docker ps -a

一些实战经验分享

根据我这几年的踩坑经验,给大家几个实用建议:

生产环境要这么配

双保险总是好的:

# Docker 层面设置重启策略
docker run -d --name app \
  --restart unless-stopped \
  --memory 512m \
  --cpus 1.0 \
  my-app:latest

# 系统层面加上监控
sudo systemctl enable docker-app-monitor.service

加个监控脚本

有时候容器会莫名其妙挂掉,加个定时检查更安心:

cat > /usr/local/bin/check-docker.sh << 'EOF'
#!/bin/bash
if ! docker ps | grep -q "my-container"; then
    docker start my-container
    echo "$(date): Restarted my-container" >> /var/log/docker-monitor.log
fi
EOF

chmod +x /usr/local/bin/check-docker.sh
echo "* * * * * /usr/local/bin/check-docker.sh" | crontab -

Docker 本身也要开机自启

别忘了 Docker 服务本身也得开机自启:

# 检查状态
sudo systemctl is-enabled docker

# 如果没启用就启用
sudo systemctl enable docker

顺便优化下 Docker 配置:

sudo nano /etc/docker/daemon.

加上这些配置:

{
  "live-restore": true,
  "log-driver": "-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

故障排查常用命令

出问题时这些命令会很有用:

# 看 Docker 日志
sudo journalctl -u docker.service

# 看容器日志
docker logs my-container

# 看启动顺序
systemd-analyze critical-chain

# 检查服务依赖
systemctl list-dependencies docker.service

常见问题怎么解决

容器之间有依赖关系

如果你的容器得按顺序启动,Docker Compose 可以用 depends_on,或者写个启动脚本:

#!/bin/bash
docker start database
sleep 10
docker start webapp

网络没就绪容器就启动了

可以在 systemd 服务里加个等待时间:

ExecStartPre=/bin/sleep 10
ExecStart=/usr/bin/docker start my-container

磁盘挂载没准备好

加上依赖配置:

[Unit]
Requires=local-fs.target
After=local-fs.target

到底选哪种?

最后总结一下,不同场景用不同方案:

  • 个人开发环境:直接用 --restart always 或者 --restart unless-stopped,简单省事
  • 生产环境单容器:systemd 服务 + Docker 重启策略,双重保障
  • 生产环境多容器:Docker Compose + systemd,专业规范

如果只想要最快速的解决方案,就这两条命令:

# 对现有容器
docker update --restart always 容器名

# 对新容器
docker run -d --restart always --name 容器名 镜像名

搞定!以后服务器重启就不用再操心容器能不能自己起来了。希望这篇文章对你有帮助,有问题欢迎在评论区交流~