文章目录
-
-
- [1. no (默认策略)](#1. no (默认策略))
- [2. on-failure[:max-retries]](#2. on-failure[:max-retries])
- [3. always](#3. always)
- [4. unless-stopped](#4. unless-stopped)
- [📊 策略对比总结表](#📊 策略对比总结表)
- [🛠️ 如何设置和修改](#🛠️ 如何设置和修改)
-
- [1. 创建容器时设置](#1. 创建容器时设置)
- [2. 更新已存在容器的策略](#2. 更新已存在容器的策略)
- [3. 在 Docker Compose 中设置](#3. 在 Docker Compose 中设置)
- [⚠️ 注意事项与最佳实践](#⚠️ 注意事项与最佳实践)
- [✅ 推荐选择](#✅ 推荐选择)
-
Docker 容器的重启策略(Restart Policy)决定了当 容器退出(Exit)或 Docker daemon 重启 时,容器应该如何行为。合理配置重启策略对于保证服务的高可用性至关重要。
Docker 提供了 4 种主要的重启策略:
1. no (默认策略)
-
含义 :容器退出后,不自动重启。
-
适用场景 :
- 一次性任务(如数据迁移、批量处理脚本)。
- 调试阶段,希望容器停止后保留现场以便检查日志。
-
示例 :
bash$ docker run --restart=no -itd centos:1.0 /bin/bash 615f9ee50e3fcbf15235d1a9396912f7e51d9da25420073e1d6703fcf429f279 $ docker inspect 615f9ee50e3fcbf | jq '.[0].HostConfig.RestartPolicy' { "Name": "no", "MaximumRetryCount": 0 } # 或者省略,因为这是默认值 $ docker run -itd centos:1.0 /bin/bash b6b2e24fc9486e0e70d15ce05ace59c438193a53cd495b8590e13edbc458f259 $ docker inspect b6b2e24fc9 | jq '.[0].HostConfig.RestartPolicy' { "Name": "no", "MaximumRetryCount": 0 }
2. on-failure[:max-retries]
-
含义 :只有当容器以非零状态码(即发生错误/异常)退出时,才自动重启。如果容器正常退出(状态码为 0),则不会重启。
-
可选参数 :
:max-retries指定最大重试次数。超过次数后不再重启。 -
适用场景 :
- 需要容错的服务,但如果是正常结束(如任务完成)则不需要重启。
- 防止无限重启循环导致资源耗尽。
-
示例 :
bash# 出错时重启,最多重试 5 次 $ docker run --restart=on-failure:5 -itd centos:1.0 /bin/bash 000244f7eb8d2509b68da5ec9c2a0ad8c92ba759aa48458557e0e8bc4701efec $ docker inspect 000244f7eb8d | jq '.[0].HostConfig.RestartPolicy' { "Name": "on-failure", "MaximumRetryCount": 5 } # 出错时无限重试 $ docker run --restart=on-failure -itd centos:1.0 /bin/bash 9bedd20adb5a15019564ff9414e9b318ebaa15c2829b6a27b4350deba3d6d32b $ docker inspect 9bedd20adb5a | jq '.[0].HostConfig.RestartPolicy' { "Name": "on-failure", "MaximumRetryCount": 0 }
3. always
-
含义 :无论容器因何种原因退出(无论是错误退出还是正常退出),Docker Daemon 都会尝试重启它。此外,如果 Docker Daemon 本身重启了,该容器也会自动启动。
-
注意 :如果容器是手动停止的(
docker stop),它不会被自动重启,直到你手动启动它或 Docker Daemon 重启。 -
适用场景 :
- 长期运行的后台服务(如 Web 服务器、数据库、API 服务)。
- 要求高可用性,必须保证容器始终处于运行状态。
-
示例 :
bash$ docker run --restart=always -itd centos:1.0 /bin/bash f927795ebea74537445c5617c19eee22ccdf0b978835bf8eb042843ac8fa27b4 $ docker inspect f927795ebea7 | jq '.[0].HostConfig.RestartPolicy' { "Name": "always", "MaximumRetryCount": 0 }
4. unless-stopped
-
含义 :与
always非常相似,无论容器因何种原因退出都会重启。唯一的区别在于 Docker Daemon 重启时的行为 :- 如果在 Docker Daemon 重启之前 ,容器是被手动停止的(
docker stop),那么 Daemon 重启后,该容器保持停止状态,不会自动启动。 - 如果容器是在运行状态下 Daemon 重启的,它会随 Daemon 一起启动。
- 如果在 Docker Daemon 重启之前 ,容器是被手动停止的(
-
适用场景 :
- 生产环境中最推荐的策略。
- 当你维护服务器重启 Docker 服务时,不希望那些你故意停掉进行维护的容器自动跑起来。
-
示例 :
bash$ docker run --restart=unless-stopped -itd centos:1.0 /bin/bash 2b1ad8e1c2de78646e976d6c77b8c0c8f1b04a1a3c0d8704f5e558457f9f78e0 $ docker inspect 2b1ad8e1c2de7 | jq '.[0].HostConfig.RestartPolicy' { "Name": "unless-stopped", "MaximumRetryCount": 0 }
综上,
"MaximumRetryCount": 0并不意味着只重启0次,在重启策略为always/unless-stopped 以及on-failure 不指定次数时含义是无限。
📊 策略对比总结表
| 策略 | 容器异常退出 (Error) | 容器正常退出 (Exit 0) | Docker Daemon 重启后 | 手动 docker stop 后 Daemon 重启 |
|---|---|---|---|---|
no |
❌ 不重启 | ❌ 不重启 | ❌ 不启动 | ❌ 不启动 |
on-failure |
✅ 重启 | ❌ 不重启 | ✅ 启动 (若上次是异常退出) | ❌ 不启动 |
always |
✅ 重启 | ✅ 重启 | ✅ 启动 | ✅ 自动启动 ⚠️ |
unless-stopped |
✅ 重启 | ✅ 重启 | ✅ 启动 | ❌ 保持停止 ✅ |
💡 核心区别 :
always和unless-stopped的主要区别在于手动停止后,Docker 服务重启是否会再次拉起容器 。生产环境通常推荐unless-stopped,因为它更符合运维直觉(我停了你别动)。
🛠️ 如何设置和修改
1. 创建容器时设置
bash
docker run --restart=unless-stopped -itd centos:1.0 /bin/bash
2. 更新已存在容器的策略
如果容器已经运行,可以使用 update 命令修改策略,无需重建容器:
bash
docker update --restart=always my_container_name
3. 在 Docker Compose 中设置
在 docker-compose.yml文件中:
yaml
version: '3'
services:
web:
image: nginx
restart: unless-stopped # 可选值: no, on-failure, always, unless-stopped
db:
image: postgres
restart: on-failure:5 # 出错最多重试5次
⚠️ 注意事项与最佳实践
-
避免重启风暴 :
如果应用代码有 Bug 导致启动即崩溃,使用
always或on-failure会导致容器无限重启,消耗大量 CPU 和日志空间。- 建议 :结合健康检查(Healthcheck)或使用监控系统报警。对于开发环境,可以使用
on-failure:3限制次数。
- 建议 :结合健康检查(Healthcheck)或使用监控系统报警。对于开发环境,可以使用
-
启动延迟(Back-off) :
Docker 在重启容器时有一个指数退避机制(Exponential Backoff)。
- 第一次重启等待 100ms
- 第二次 200ms
- 第三次 400ms
- ...
- 最长等待时间约为 1 分钟。
这可以防止容器在短时间内频繁重启拖垮宿主机。
-
依赖顺序 :
重启策略是独立的。如果容器 A 依赖容器 B,而 B 重启了,A 不会自动感知并重启。如果需要处理依赖关系,建议使用 Docker Compose 的
depends_on配合健康检查,或使用 Kubernetes 等编排工具。 -
日志轮转 :
频繁重启会产生大量日志。务必配置 Docker 的日志驱动(logging driver)进行日志轮转(log rotation),防止磁盘写满。
bashdocker run --log-opt max-size=10m --log-opt max-file=3 ...
✅ 推荐选择
- 生产环境长期服务 :
unless-stopped - 临时任务/批处理 :
no - 不稳定但需尝试恢复的服务 :
on-failure:5