我在 Ubuntu 服务器上运行了许多 docker 容器。它们由 systemd 控制。
如果我运行,容器将正常关闭。 journalctl 的输出如下(按时间倒序输出,最新的在最上面):systemctl stop [email protected]
Nov 05 10:58:11 ubox0 systemd[1]: Stopped Docker container startup for mw/salcom/app.
Nov 05 10:58:11 ubox0 docker[3622]: mw-salcom-app
Nov 05 10:58:09 ubox0 docker[3470]: [Thu Nov 05 10:58:09.921033 2020] [mpm_prefork:notice] [pid 1] AH00169: caught SIGTERM, shutting down
Nov 05 10:58:09 ubox0 systemd[1]: Stopping Docker container startup for mw/salcom/app...
但是如果我执行shutdown -h now
,我会得到:
Nov 05 10:51:04 ubox0 systemd[1]: Stopped Docker container startup for mw/salcom/app.
Nov 05 10:51:04 ubox0 systemd[1]: [email protected]: Failed with result 'timeout'.
Nov 05 10:51:04 ubox0 systemd[1]: [email protected]: Main process exited, code=killed, status=9/KILL
Nov 05 10:51:04 ubox0 systemd[1]: [email protected]: Killing process 2077 (docker) with signal SIGKILL.
Nov 05 10:51:04 ubox0 systemd[1]: [email protected]: State 'stop-sigterm' timed out. Killing.
Nov 05 10:50:04 ubox0 systemd[1]: [email protected]: Stopping timed out. Terminating.
Nov 05 10:49:04 ubox0 systemd[1]: Stopping Docker container startup for mw/salcom/app...
容器没有停止,并且该过程最终在 2 分钟后超时并且容器中止。
这是什么原因呢?
我希望我的容器能够正常关闭,以便其中运行的服务停止且不会丢失数据。
我的服务文件是:
[Unit]
Description=Docker container startup for %I
Requires=docker.service
After=docker.service
[Service]
TimeoutStartSec=40
Restart=always
# wait a while before restarting in case we are doing a restore;
# this includes a 'docker stop' command after we restore the data
RestartSec=60
ExecStartPre=-/usr/bin/docker stop %i
ExecStart=/usr/bin/docker start -a %i
ExecStop=/usr/bin/docker stop %i
TimeoutStopSec=60
[Install]
WantedBy=multi-user.target
更新经过进一步搜索,我发现了这篇文章如何正确地将 Docker 容器作为 systemd 服务来处理?描述了同样的问题,但没有答案。
答案1
看起来 docker 和 systemd 并不总是能很好地相处,请参阅:
我在另一台机器(我的备份服务器)上进行了完全相同的设置,这里一切正常。我可以执行关机命令,并且所有 docker 容器都会正常关闭。
所以问题可能是依赖关系问题。也许 systemd 关闭了 docker 容器所需的某些服务,以便它们能够正常关闭。
在“失败”的系统上,docker 版本是18.09.2
,在“运行”的系统上,docker 版本是18.06.1-ce
。
这发行说明对于docker版本18.09
状态:
In Docker versions prior to 18.09, containerd was managed
by the Docker engine daemon. In Docker Engine 18.09,
containerd is managed by systemd.
当我将以下几行添加到我的单元文件中时:
[Unit]
...
Requires=containerd.service
After=containerd.service
并重新加载单元文件(systemctl daemon-reload
),一切又开始正常工作了。我的容器并没有在我设置的 1 分钟超时后终止,而是在几秒钟后关闭了。
我尝试将 docker 升级到版本20.10.1
一,但无济于事。
当我遇到以下情况时,我想到了这个“解决方案”的想法:https://github.com/sous-chefs/docker/issues/1062