Docker.service 耗时 1 分 30 秒,导致启动缓慢

Docker.service 耗时 1 分 30 秒,导致启动缓慢

我在 Linux Mint 19 上使用 Cinnamon 3.8.8,
我有一台 Nvidia GT740 和 8GB RAM

我使用的是:
Docker 版本 18.06.1-ce,构建 e68fc7a docker-machine 版本 0.14.0,构建 89b8332 docker-compose 版本 1.21.2,构建 a133471

我注意到我的启动速度非常慢

所以我跑了:

systemd-analyze blame

我得到了以下信息:

1min 27.764s docker.service
     39.269s plymouth-quit-wait.service
     24.180s dev-sdb2.device
     20.645s nmbd.service
     18.437s snapd.service
     13.111s systemd-journal-flush.service
     12.475s udisks2.service
     12.446s NetworkManager.service
     10.969s keyboard-setup.service
     10.734s libvirtd.service
     10.418s NetworkManager-wait-online.service
     10.168s networkd-dispatcher.service
     10.065s smbd.service
     9.736s apparmor.service
     ..... etc

正如您所看到的,docker.service 花费了大量的时间,有人知道如何解决这个问题吗?

答案1

我注意到这个问题已经存在好几年了,但是今天我在具有以下规格的开发系统上遇到了同样的问题:

  • Ubuntu 20.04
  • Docker 20.10.17
  • docker-compose 1.25.0

Docker.service 在我的系统上花费了超过 10 分钟的时间,并且它在最终启动时劫持了 multi-user.target 和 graphic.target,导致我的系统在此过程中非常不稳定。(您可以在屏幕上移动光标,但您运行的程序需要等待很长时间才能真正启动)

由于我的系统是一台开发机器并且没有运行关键基础设施,所以我只是禁用了该服务:

sudo systemctl disable docker

删除启动时重启也有助于长期保持这种状态。检查您的服务单元文件。systemctl cat docker.service如果您always服务节中写着“重新启动”,您可以将其更改为on-failure仅在失败时重新启动(在您通过 docker.socket 激活有意运行它之后),这样它就不会在启动时启动,这将为您节省大量启动时间。这就是我现在使用它的方式:

[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=on-failure

containerd 服务和 docker.socket 服务仍将运行,就我而言,从目前所见,它们不需要很长时间即可激活(30 秒以下)。

当需要时,docker.socket 会生成一个新的 docker.service(如果你运行 docker 或 docker-compose 命令),因为此时 docker 服务正在启动整个系统已经启动并运行,等待时间大大减少,因为此时 docker.service 所依赖的任何其他东西都已在运行并处于活动状态。

这是我在系统上禁用 docker 服务并重新启动几次之后,在进行日常 web 开发工作时观察到的情况。

答案2

基于本文我跑了:

❯ systemd-analyze critical-chain
The time when unit became active or started is printed after the "@" character.
The time the unit took to start is printed after the "+" character.

graphical.target @42.222s
└─multi-user.target @42.221s
  └─docker.service @38.091s +4.129s
    └─network-online.target @38.082s
      └─NetworkManager-wait-online.service @4.450s +33.629s
        └─NetworkManager.service @4.330s +69ms
          └─network-pre.target @4.268s

这表明,docker 等待网络才是真正的罪魁祸首。

然后sudo systemctl edit docker我复制了该After行并删除了network-online.target,最后得到如下结果:

After=docker.socket firewalld.service containerd.service time-set.target

这为那些希望在启动时准备好docker的人提供了一个合适的解决方案:)

相关内容