如何让 Docker 容器在系统启动时自动启动?

Posted

技术标签:

【中文标题】如何让 Docker 容器在系统启动时自动启动?【英文标题】:How do I make a Docker container start automatically on system boot? 【发布时间】:2015-08-07 13:58:24 【问题描述】:

假设我有一个想要运行的 Docker 容器,那么我可以调用

$ docker run ...

一切都很好。如果系统崩溃并重新启动,是否有一种内置方式可以自动重新启动容器?

如果是这样,这在 Docker Compose 中是否也可用?

【问题讨论】:

【参考方案1】:

blog post 很好地描述了 2021 年的答案。默认情况下,docker 已安装但未启用。如果您使用的是最新的 Ubuntu(例如 20)并且您通过 apt 安装了 docker,那么您所要做的就是 sudo systemctl enable --now docker

这将在 systemd 中启用 docker 服务并在它尚未启动时立即启动它。 docker 服务在安装时不会启动,但是任何使用 docker 套接字的 docker 命令(例如,docker ps)都会导致 systemd 启动服务。启用该服务将导致它在每次启动时启动。

【讨论】:

投反对票但没有评论?有错误吗? 问题是关于启动 容器,而不是 Docker 守护进程【参考方案2】:

要启动容器并将其设置为在系统重新启动时自动重新启动,请使用

docker run -d --restart unless-stopped ecstatic_ritchie

其中ecstatic_ritchie 是指定感兴趣容器的示例名称。使用docker ps -a 列出所有容器名称。

使特定运行的容器在系统重启时自动启动

docker update --restart unless-stopped ecstatic_ritchie

让所有正在运行的容器在系统重启时自动启动

docker update --restart unless-stopped $(docker ps -q)

查看更多关于 Docker homepage

【讨论】:

【参考方案3】:

我在运行 Linux 系统时遇到了类似的问题。系统启动后,重启策略为“除非停止”的容器不会自动重启,除非我输入了以某种方式使用 docker 的命令,例如“docker ps”。我很惊讶,因为我预计该命令只会报告一些状态信息。接下来我尝试了命令“systemctl status docker”。在没有运行 docker 命令的系统上,此命令报告以下内容:

● docker.service - Docker Application Container Engine

   Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled)

     Active: inactive (dead)    TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com

在没有其他 Docker 命令的情况下运行“docker ps”的系统上,我得到了以下信息:

● docker.service - Docker Application Container Engine
    Loaded: loaded (/lib/systemd/system/docker.service; disabled; vendor preset: enabled)

    Active: active (running) since Sun 2020-11-22 08:33:23 PST; 1h 25min ago

TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com

   Main PID: 3135 (dockerd)
      Tasks: 13

    Memory: 116.9M
     CGroup: /system.slice/docker.service
             └─3135 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
 ... [various messages not shown ]

最可能的解释是 Docker 在完全初始化和启动容器之前会等待一些 docker 命令。在初始化容器所需的所有服务之后,您可能可以在 systemd 单元文件中运行“docker ps”。我已经通过将一个名为 docker-onboot.service 的文件放在目录 /lib/systemd/system 中进行了测试,其中包含以下内容:

[Unit]
# This service is provided to force Docker containers
# that should automatically restart to restart when the system
# is booted. While the Docker daemon will start automatically,
# it will not be fully initialized until some Docker command
# is actually run.  This unit merely runs "docker ps": any
# Docker command will result in the Docker daemon completing
# its initialization, at which point all containers that can be
# automatically restarted after booting will be restarted.
#
Description=Docker-Container Startup on Boot
Requires=docker.socket
After=docker.socket network-online.target containerd.service

[Service]
Type=oneshot
ExecStart=/usr/bin/docker ps

[Install]

WantedBy=multi-user.target

到目前为止(一项测试,启用此服务),容器在计算机启动时启动。我没有尝试对 docker.service 的依赖,因为 docker.service 在运行 docker 命令之前不会启动。下一个测试将禁用 docker-onboot(查看 WantedBy 依赖项是否会自动启动它)。

【讨论】:

在启动时使用systemctl enable docker.service 启动docker.service 比创建一个完整的其他服务只是通过其套接字间接触发该服务要容易得多。【参考方案4】:

您可以使用docker update --restart=on-failure <container ID or name>

顾名思义,on-failure 不仅会在失败时重新启动容器,还会在系统启动时重新启动。

根据documentation,有多个重启选项:

Flag            Description
no              Do not automatically restart the container. (the default)
on-failure      Restart the container if it exits due to an error, which manifests as a non-zero exit code.
always          Always restart the container if it stops. If it is manually stopped, it is restarted only when Docker daemon restarts or the container itself is manually restarted. (See the second bullet listed in restart policy details)
unless-stopped  Similar to always, except that when the container is stopped (manually or otherwise), it is not restarted even after Docker daemon restarts.

【讨论】:

很好地发现了这一点,考虑到文档中没有提到它。对我来说完美的解决方案。 关于使用on-failure需要注意的一点,如果你有一个容器依赖于另一个已经在运行的容器,似乎没有“启动顺序”,所以一个可能启动并立即失败并且永远不会在操作系统启动时启动 这对我也有帮助,sudo systemctl restart docker 证实了这一点。很好看!【参考方案5】:

您可以通过以下方式运行始终重启的容器:

$ docker run -dit --restart unless-stopped <image name OR image hash>

如果您想更改正在运行的容器的配置,您应该通过以下方式更新它:

$ docker update --restart=<options> <container ID OR name>

如果你想查看容器的当前策略,首先在上面运行以下命令:

docker inspect gateway | grep RestartPolicy -A 3

毕竟,别忘了让已安装的 docker daemon 在系统启动时启用

$ systemctl enable docker

要查看重启策略的完整列表,请参阅:Restart Policies

【讨论】:

【参考方案6】:

1) 首先,你必须在启动时启用 docker 服务

$ sudo systemctl enable docker

2) 如果你有 docker-compose .yml 文件添加 restart: always 或者如果你有 docker 容器添加 restart=always 像这样:

docker run --restart=always 并运行 docker 容器

确定

如果你手动停止一个容器,它的重启策略会被忽略,直到 Docker 守护进程重启或者容器被手动重启。

在 Docker 官方页面上看到这个restart policy

3) 如果你想启动 docker-compose,所有的服务都会在你重启系统时运行所以你只运行下面的命令一次

$ docker-compose up -d

【讨论】:

【参考方案7】:

这就是 crontab 的用途:

@reboot sleep 10 ; docker start <container name> 2>&1 | /usr/bin/logger -t 'docker start'

通过crontab -e 访问您的用户crontab 或使用crontab -l 显示它或在/etc/crontab 编辑您的系统crontab

【讨论】:

什么是 cron 服务在 docker 服务之前启动...在这种情况下会失败... @AkhilJalagam 我不确定我是否理解您的问题。 “sleep 10”给 crond 足够的时间来启动,然后在系统启动/重启后启动容器。这种方法在启动前不需要任何人登录,并且避免了混乱、复杂的 systemd 服务单元。 systemd 服务单元方法感觉比我的示例更 hacky。【参考方案8】:

我想在 Windows 上实现 on-boot 容器启动。

因此,我刚刚创建了一个在系统启动时启动的计划任务。该任务只需启动“Docker for Windows.exe”(或任何 docker 可执行文件的名称)。

然后,所有重启策略为“always”的容器都会启动。

【讨论】:

【参考方案9】:

default restart policy 是 no

对于创建的容器,使用docker update 更新重启策略。

docker update --restart=always 0576df221c0b

0576df221c0b 是容器 ID。

【讨论】:

always 不是意味着即使 I 停止容器也会重新启动?当然有一种方法可以在重新启动时重新启动容器,而无需这种持续启动... @Marc:没有。见documentation:If you manually stop a container, its restart policy is ignored until the Docker daemon restarts or the container is manually restarted. This is another attempt to prevent a restart loop. 有没有办法在 docker 守护进程启动时启动一个(一系列)容器,但不尝试在错误时重新启动?我没找到(当然是使用重启策略)。【参考方案10】:

文档中的更多“温和”模式:

docker run -dit --restart unless-stopped <image_name>

【讨论】:

不幸的是,当 docker 守护进程因重启而停止时,守护进程“停止”容器,将它们标记为已停止。然后当系统启动时,它实际上并没有启动这些。这是愚蠢的。这是错误:github.com/docker/for-linux/issues/652 restart=unless-stopped 选项将在 docker 引擎重新启动时尝试启动容器。我看到的例外情况是 docker 引擎本身未配置为在重新启动时自动启动(检查systemctl status docker 以确保它已启用)并且引擎在网络准备好之前启动容器,我只看到过覆盖网络。这两个都会破坏restart=always【参考方案11】:

如果您希望即使没有用户执行登录也启动容器(例如我只启动并且不想每次登录的 VirtualBox VM)。以下是我为 Ubuntu 16.04 LTS 执行的步骤。例如,我安装了一个 oracle db 容器:

$ docker pull alexeiled/docker-oracle-xe-11g
$ docker run -d --name=MYPROJECT_oracle_db --shm-size=2g -p 1521:1521 -p 8080:8080 alexeiled/docker-oracle-xe-11g
$ vim /etc/systemd/system/docker-MYPROJECT-oracle_db.service

并添加以下内容:

[Unit]
Description=Redis container
Requires=docker.service
After=docker.service

[Service]
Restart=always
ExecStart=/usr/bin/docker start -a MYPROJECT_oracle_db
ExecStop=/usr/bin/docker stop -t 2 MYPROJECT_oracle_db

[Install]
WantedBy=default.target

并在启动时启用服务

sudo systemctl enable docker-MYPROJECT-oracle_db.service

欲了解更多信息https://docs.docker.com/engine/admin/host_integration/

【讨论】:

对于那些希望使用 docker-compose 执行此操作的人,您可以将上面的 docker 命令替换为 docker-compose 命令,使用 -f 标志来指定 docker-compose 的位置文件:/usr/bin/docker-compose -f /path/to/docker-compose.yml up 补充一下@charlesreid1 所说的,如果您的docker-compose.yml 指定了.env 文件,请使用--project-directory /path/to 除了 明确指定您的docker compose 文件。 Docker 有自己的日志系统和进程管理器。很遗憾,它没有正确的重启策略。 知道如何在 Windows Server 2012 上执行此操作吗?除非我登录,否则我无法运行 docker... 完整披露:文档实际上声明您不想这样做:“Docker 建议您使用重启策略,并避免使用进程管理器来启动容器。” docs.docker.com/config/containers/…【参考方案12】:

是的,docker 有restart policies,例如docker run --restart=always,可以处理这个问题。这也可以在compose.yml config file 中作为restart: always 使用。

【讨论】:

这是第一个并且被接受的答案,但是可能大多数搜索该功能的人真的希望将他们的容器作为服务运行。 @kon 's answer using Systemd as service manager 是为此目的的最佳解决方案之一,需要更多的支持。 这对我不起作用。我有一个名为“crmpicco-mysql”的容器,我运行了docker run --restart=always crmpicco-mysql,但出现错误:Unable to find image 'crmpicco-mysql:latest' locally 您的错误与此无关。您可能想发布一个单独的问题,但看起来您混淆了 docker 映像名称和 docker 容器名称。 docker run 命令需要您可以通过 docker images 列出的图像名称。 唯一的问题是,当容器因错误而停止时,“always”也会无限重启(参见文档)。应该有一个只在 daemon-start 上启动的策略 我认为容器 / docker 的主要卖点之一是我不需要在 systemd 中安装和管理我的每个服务(这可能会很痛苦)。

以上是关于如何让 Docker 容器在系统启动时自动启动?的主要内容,如果未能解决你的问题,请参考以下文章

让docker 容器开机自动启动

Docker容器开机自动启动

如何避免Docker容器启动脚本运行后自动退出

docker容器的启动删除,杀进程,自动重启等操作

Ubuntu18.04 设置开机启动docker

38-Docker-修改docker容器启动命令