一、问题背景
在 CentOS、Ubuntu 等 Linux 服务器上,Docker 可能在系统网络尚未完全就绪时启动,导致容器网络初始化或端口映射出现异常。
通过 systemd 配置,可以让 Docker 在网络达到 network-online.target 之后启动,降低开机阶段出现网络竞态的概率。
适用范围 :本方案主要优化服务器开机时的 Docker 启动顺序;并不能保证网络服务在运行期间重启后,Docker 会自动恢复失效的端口映射。
二、配置 Docker 启动顺序
1. 创建 systemd 覆盖配置
CentOS / Ubuntu 通用:
sudo systemctl edit docker.service
在打开的编辑器中加入:
ini
[Unit]
Wants=network-online.target
After=network-online.target
After=firewalld.service
配置说明:
| 配置项 | 作用 |
|---|---|
Wants=network-online.target |
Docker 启动时,尝试拉起网络就绪目标。 |
After=network-online.target |
规定 Docker 必须排在网络就绪目标之后启动。 |
After=firewalld.service |
如果 firewalld.service 也在启动事务中,则让 Docker 排在它后面启动。 |
注意:
After=只定义启动先后顺序,不会主动启动所指定的服务。因此,After=firewalld.service不等于启用或启动 firewalld。- Ubuntu 常见防火墙管理工具为 UFW,通常没有运行
firewalld.service;这一行在没有该服务时可以省略。 network-online.target是否确实等待网络就绪,取决于对应的等待服务是否正确配置,如NetworkManager-wait-online.service或systemd-networkd-wait-online.service。- 建议使用
systemctl edit添加 drop-in 配置,不要直接修改系统自带的/usr/lib/systemd/system/docker.service或/lib/systemd/system/docker.service。
2. 重新加载 systemd 配置
sudo systemctl daemon-reload
新配置将在 Docker 下一次启动时生效。可以在合适的维护窗口重启 Docker 以验证配置:
sudo systemctl restart docker
注意:重启 Docker 可能中断正在运行的容器或其网络连接,生产环境应安排维护窗口。
三、验证配置是否生效
1. 查看完整 unit 配置
bash
systemctl cat docker.service
检查输出中是否包含新增的 drop-in 内容。
2. 查看依赖及启动顺序
css
systemctl show docker.service -p After -p Wants
确认 After 中包含 network-online.target,Wants 中包含 network-online.target。
3. 检查网络等待服务(按实际网络管理方式)
如果系统使用 NetworkManager:
lua
systemctl status NetworkManager-wait-online.service
如果系统使用 systemd-networkd:
lua
systemctl status systemd-networkd-wait-online.service
应根据系统实际采用的网络管理器配置等待服务,不要同时盲目启用多个网络管理器。
四、配置能解决什么,不能解决什么?
| 场景 | 本配置的效果 |
|---|---|
| 服务器开机时 Docker 早于网络就绪启动 | 可降低启动竞态导致的异常概率。 |
| Docker 初始化网桥时依赖的网络条件未满足 | 可以改善部分因开机时序造成的问题。 |
运行期间执行 systemctl restart NetworkManager |
不能保证自动恢复 Docker 网络。 |
| 运行期间重启 firewalld / UFW 后端口映射不可访问 | 不能保证自动修复丢失或变更的防火墙/NAT 规则。 |
| Docker 网桥被 NetworkManager 或其他网络服务接管 | 不能解决,需要调整网络管理规则。 |
五、运行期间网络重启造成端口映射失效的排查方向
如果 Docker 已正常启动,但重启网络服务后容器端口无法访问,建议按以下方向定位根因:
- 检查 Docker 服务与容器状态 :使用
systemctl status docker、docker ps确认服务与容器是否仍正常运行。 - 检查端口发布配置 :使用
docker ps和docker port <容器名或ID>,确认端口仍然按预期发布。 - 检查防火墙及 NAT 规则:核查 firewalld、UFW、iptables 或 nftables,确认网络重启时是否刷新、覆盖了 Docker 创建的规则。
- 检查 Docker 网桥管理归属 :确认
docker0、br-*等接口没有被 NetworkManager 或其他网络管理器错误接管。 - 检查 Docker daemon 配置 :确认
/etc/docker/daemon.json中没有意外关闭 Docker 的防火墙规则管理(如"iptables": false);注意不同 Docker 网络后端及版本的配置差异。 - 检查服务日志 :通过
journalctl -u docker -b和对应网络、防火墙服务日志定位规则被清理或接口被重建的时间点。
建议:优先修复造成 Docker 网桥或防火墙规则异常的服务配置,避免将每次网络重启后执行 systemctl restart docker 作为长期解决方案。
六、总结
通过下面的 systemd drop-in 配置,可以优化 Docker 的开机启动顺序:
ini
[Unit]
Wants=network-online.target
After=network-online.target
After=firewalld.service
其中 After=firewalld.service 应根据服务器实际是否使用 firewalld 决定是否保留。
核心结论:
- 开机启动问题 :通过
network-online.target优化依赖与顺序。 - 运行期间网络重启问题:应检查防火墙/NAT 规则及 Docker 网桥的管理冲突,针对根因修复。
- 不要混淆"网络就绪后启动 Docker"与"网络重启后自动恢复 Docker 端口映射"这两类问题。