docker-compose 等待启动,直到挂载主机文件系统

Posted

技术标签:

【中文标题】docker-compose 等待启动,直到挂载主机文件系统【英文标题】:docker-compose wait to launch until a host filesystem is mounted 【发布时间】:2021-04-01 19:21:58 【问题描述】:

这个问题的重点是强制 docker-compose 等待启动 mysql 容器,直到挂载主机文件系统。在我的例子中,主机文件系统保存着 mysql 数据库文件。

对于依赖于 mysql 容器的服务,有一些脚本,例如 wait-for-it,它们作为容器入口点的一部分运行。这些脚本检查网络端口上服务的可用性。但我看不到如何让容器启动等待文件系统安装在主机上。

当主机启动时,NFS 和 RAID 文件系统的启动速度可能不如容器启动的快。如果文件系统在容器启动后挂载到主机上,则容器中的绑定卷不会更新。然后容器最终无法访问已安装/绑定的文件系统。

【问题讨论】:

假设您的系统使用 systemd(这很常见),解决方案是使 docker 服务依赖于文件系统的适当 .mount 单元。这将阻止 docker 在文件系统挂载之前启动。例如。如here所述。 很好的答案@larsks。我假设您的意思是将mnt-mountpoint.mount 添加到/lib/systemd/system/docker.serviceAfter 行的末尾。我通过卸载文件系统然后停止并启动 docker 守护进程进行了测试。不幸的是,这些容器都是从卸载文件系统开始的。接下来我将测试重新启动。 对linked question 的更彻底阅读表明,我需要将mnt-mountpoint.mount 添加到Requires 行。现在,如果文件系统未挂载,docker 服务将拒绝启动。 @larsks 请发布您的答案,以便我接受。 【参考方案1】:

假设您的系统使用 systemd(这很常见),解决方案是让 docker 服务依赖于文件系统的适当 .mount 单元。这将阻止 docker 在文件系统挂载之前启动。描述了添加对挂载点的依赖项,例如in this answer 结束 https://unix.stackexchange.com。

对于/etc/fstab 中列出的每个文件系统,systemd 都会生成一个名为<filesystem>.mount 的单元。例如,在我的系统上,/etc/fstab 包含以下内容:

/dev/tank/scratch /scratch xfs defaults 1 2

我看到以下 systemd 单元:

# systemctl list-units -t mount |grep scratch
scratch.mount        loaded active mounted /scratch

我们可以通过在单元的[Unit] 部分添加类似以下内容来使 Docker 等服务依赖于这个挂载点:

[Unit]
Requires=scratch.mount
After=scratch.mount

Requires 指令的意思是“当你启动这个服务时(例如docker),也启动这里列出的单元”,After 指令的意思是“启动这个之前的命名单元”。

【讨论】:

我相信这是正确的答案,但不幸的是它在系统启动期间对我不起作用。我认为这是因为 systemd 有一个 4 岁的 bug 正好涉及这种使用模式。我很难理解像 systemd 这样被数百万(?)Linux 主机使用的实用程序如何存在这样的错误。变通办法的贡献将不胜感激。我的 Ubuntu 18 系统运行 systemd 版本 237。 啊,真糟糕,我以为你表示它正在工作。明天有空的时候再仔细看看。 谢谢。它在您停止并启动 docker 守护程序之后 启动时起作用,但不是作为启动过程的一部分。【参考方案2】:

最低级别的服务是mysql。修改它的入口点以在已知位于已挂载文件系统上的目录丢失时退出。

所有依赖服务都可以使用dockerizewait-for-it脚本等待mysql网络端口打开。

  mysql:
        image: mysql:5.7.30
        restart: always
        entrypoint: ["bash", "-c", "touch /testdir/dir_on_filesystem/write-test && rm /testdir/dir_on_filesystem/write-test && echo 'Test for mounted filesystem passed' && mysqld --user=root"]
        volumes:
          - /mnt/mountpoint/mysql:/var/lib/mysql
          - /mnt/mountpoint:/testdir

如果你能保证/mnt/mountpoint/mysqlmysql容器第一次启动之前就存在于文件系统中,那么你可以使用那个目录代替/testdir/dir_on_filesystem进行测试。

请注意,此入口点测试还确保文件系统不是以只读方式安装的。当 RAID 阵列在系统引导期间重新同步时,它可以以只读状态开始,直到重新同步取得一些进展。可写性检查并不是绝对必要的,因为如果 mysql 容器无法写入其数据库文件,它将退出。

【讨论】:

以上是关于docker-compose 等待启动,直到挂载主机文件系统的主要内容,如果未能解决你的问题,请参考以下文章

Docker部署Docker-compose部署redis容器及启动失败挂载失败等问题

Docker部署Docker-compose部署redis容器及启动失败挂载失败等问题

docker-compose内mysql 挂载数据库目录,启动时mysql容器自动退出

Docker Compose 在启动 Y 之前等待容器 X

在主线程上启动对话框等待工作线程的结果

使用docker-compose时,Healthcheck根本不起作用(我的服务在启动前不等待Kafka启动)