首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >CentOS 上如何确保挂载NFS完成后再启动 Docker:从踩坑到最终解决方案

CentOS 上如何确保挂载NFS完成后再启动 Docker:从踩坑到最终解决方案

作者头像
不止于python
发布2025-07-27 13:34:10
发布2025-07-27 13:34:10
17200
代码可运行
举报
文章被收录于专栏:不止于python不止于python
运行总次数:0
代码可运行

前言

如果你的 Docker 容器依赖远程存储(如 NFS 共享目录),而服务器开机时 挂载顺序晚于 Docker 启动,容器就会无法访问挂载点,频繁报错,甚至导致整个服务无法运行。 本文通过一个实际案例,手把手实现:CentOS 上自动挂载远程存储,并在挂载完成后再启动 Docker,并讲清楚 systemd 配置路径、Docker 配置两种修改方式,避免升级风险。

1. 问题现象

假设我们想把远程存储挂载到 /data,在 /etc/fstab 中写了:

代码语言:javascript
代码运行次数:0
运行
复制
storage.example.com:/share /data nfs defaults,_netdev 0 0

重启后发现:

  • • 日志出现:mount.nfs: Failed to resolve server … Name or service not known
  • • Docker 启动,但容器无法访问 /data
  • • 手动执行 systemctl start data.mount 却能正常挂载。

2. 为什么会这样?

启动时,systemd 只保证网络接口启动 (network.target),但:

  • DNS 服务可能还没就绪(无法解析远程主机);
  • NFS 挂载失败,目录没挂上
  • • Docker 没有等待挂载完成,直接启动;
  • • 即使挂载后来补上,容器内卷也已初始化失败。

3. 常见但不稳定的“解决方案”

有人会:

  • • 在 rc.local 或脚本里手动延迟挂载;
  • • Docker 设为 restart: always,依赖自动重启。

这些办法可能短期有效,但风险很大:

  • • DNS 慢、网络不稳,依旧失败;
  • • 容器可能在挂载前启动,导致卷不可用。

4. 最终解决方案

第一步:用 systemd .mount 管理挂载

创建 /etc/systemd/system/data.mount

代码语言:javascript
代码运行次数:0
运行
复制
[Unit]
Description=Mount remote storage before Docker
Requires=network-online.target nss-lookup.target NetworkManager-wait-online.service
After=network-online.target nss-lookup.target NetworkManager-wait-online.service
Before=docker.service

[Mount]
What=storage.example.com:/share
Where=/data
Type=nfs
Options=_netdev,auto,timeo=500,retrans=86400,hard,bg,intr

[Install]
WantedBy=multi-user.target

关键点:

  • NetworkManager-wait-online.service:等待网络和 DNS 就绪;
  • Before=docker.service:挂载必须先于 Docker;
  • _netdev:让 systemd 知道这是网络设备挂载。

第二步:让 Docker 等待挂载

不建议直接修改 /usr/lib/systemd/system/docker.service,因为它里面已经有其他依赖,直接替换会破坏服务启动逻辑。

推荐方法:使用 override 文件,仅追加挂载依赖:

代码语言:javascript
代码运行次数:0
运行
复制
mkdir -p /etc/systemd/system/docker.service.d
vim /etc/systemd/system/docker.service.d/override.conf

添加以下内容:

代码语言:javascript
代码运行次数:0
运行
复制
[Unit]
# 仅追加 data.mount,不覆盖原有依赖
Requires=data.mount
After=data.mount

然后重新加载,验证修改是否正确:

代码语言:javascript
代码运行次数:0
运行
复制
systemctl daemon-reload
systemctl show docker.service | grep -E 'Requires|After'

你会看到原本的依赖(如 containerd.servicenetwork-online.target)仍然存在,并额外加上了 data.mount

重启docker服务

代码语言:javascript
代码运行次数:0
运行
复制
systemctl restart docker

这样,docker.service 启动时既会依赖它原本的 containerd.servicenetwork-online.target,也会等待 data.mount 完成后再启动。

如果你真的要直接改 /usr/lib/systemd/system/docker.service,必须小心:

  • • 找到原本的 Requires=After=,把 data.mount 加进去,而不是覆盖;
  • • 升级 Docker 时,这些修改容易被覆盖,所以不推荐。

第三步:启用并验证

代码语言:javascript
代码运行次数:0
运行
复制
systemctl enable NetworkManager-wait-online.service
systemctl enable data.mount
systemctl daemon-reload
systemctl restart docker
reboot

检查状态:

代码语言:javascript
代码运行次数:0
运行
复制
systemctl status data.mount
systemctl status docker

挂载和 Docker 都会在启动时自动就绪,容器可直接访问 /data


5. systemd 三个路径的区别

理解这三个目录,才能知道配置应该改哪里。

  1. 1. /usr/lib/systemd/system/
    • • 存放软件包默认提供的服务文件(系统安装时生成)。
    • • 不建议直接改,更新时可能被覆盖。
  2. 2. /run/systemd/system/
    • • 临时,系统运行时生成的,重启后消失。
  3. 3. /lib/systemd/system/
    • • 部分发行版使用的路径,功能和 /usr/lib/systemd/system 相同。
    • • 在 CentOS/RHEL 上通常是 /usr/lib/systemd/system 的符号链接。
  4. 4. /etc/systemd/system/
    • 用户自定义和覆盖文件,优先级最高。
    • • 使用 override.conf 可以覆盖系统服务而不修改原文件。

优先级顺序:

代码语言:javascript
代码运行次数:0
运行
复制
/etc/systemd/system/ > /run/systemd/system/ > /usr/lib/systemd/system/ (/lib/systemd/system/)

查看最终生效配置:

代码语言:javascript
代码运行次数:0
运行
复制
systemctl cat docker.service

最终完整解决方案思路

  • 挂载单元 /etc/systemd/system/data.mount(使用时替换实际地址);
  • Docker 依赖挂载(通过 override,避免覆盖系统文件);
  • 启用等待网络,避免 DNS 未就绪导致挂载失败。

这样,每次服务器重启时:

  1. 1. 系统等待网络和 DNS;
  2. 2. 自动挂载 /data
  3. 3. 挂载完成后 Docker 启动,容器立即能用该目录。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1. 问题现象
  • 2. 为什么会这样?
  • 3. 常见但不稳定的“解决方案”
  • 4. 最终解决方案
    • 第一步:用 systemd .mount 管理挂载
    • 第二步:让 Docker 等待挂载
    • 第三步:启用并验证
  • 5. systemd 三个路径的区别
  • 最终完整解决方案思路
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档