【发布时间】:2015-08-07 13:58:24
【问题描述】:
假设我有一个想要运行的 Docker 容器,那么我可以调用
$ docker run ...
一切都很好。如果系统崩溃并重新启动,是否有一种内置方式可以自动重新启动容器?
如果是这样,这在 Docker Compose 中是否也可用?
【问题讨论】:
标签: docker docker-compose
假设我有一个想要运行的 Docker 容器,那么我可以调用
$ docker run ...
一切都很好。如果系统崩溃并重新启动,是否有一种内置方式可以自动重新启动容器?
如果是这样,这在 Docker Compose 中是否也可用?
【问题讨论】:
标签: docker docker-compose
blog post 很好地描述了 2021 年的答案。默认情况下,docker 已安装但未启用。如果您使用的是最新的 Ubuntu(例如 20)并且您通过 apt 安装了 docker,那么您所要做的就是 sudo systemctl enable --now docker。
这将在 systemd 中启用 docker 服务并在它尚未启动时立即启动它。 docker 服务在安装时不会启动,但是任何使用 docker 套接字的 docker 命令(例如,docker ps)都会导致 systemd 启动服务。启用该服务将导致它在每次启动时启动。
【讨论】:
要启动容器并将其设置为在系统重新启动时自动重新启动,请使用
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
【讨论】:
我在运行 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 比创建一个完整的其他服务只是通过其套接字间接触发该服务要容易得多。
您可以使用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.
【讨论】:
sudo systemctl restart docker 证实了这一点。很好看!
您可以通过以下方式运行始终重启的容器:
$ 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
【讨论】:
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
【讨论】:
这就是 crontab 的用途:
@reboot sleep 10 ; docker start <container name> 2>&1 | /usr/bin/logger -t 'docker start'
通过crontab -e 访问您的用户crontab 或使用crontab -l 显示它或在/etc/crontab 编辑您的系统crontab
【讨论】:
我想在 Windows 上实现 on-boot 容器启动。
因此,我刚刚创建了一个在系统启动时启动的计划任务。该任务只需启动“Docker for Windows.exe”(或任何 docker 可执行文件的名称)。
然后,所有重启策略为“always”的容器都会启动。
【讨论】:
default restart policy 是 no。
对于创建的容器,使用docker update 更新重启策略。
docker update --restart=always 0576df221c0b
0576df221c0b 是容器 ID。
【讨论】:
always 不是意味着即使 I 停止容器也会重新启动?当然有一种方法可以在重新启动时重新启动容器,而无需这种持续启动...
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 run -dit --restart unless-stopped <image_name>
【讨论】:
restart=unless-stopped 选项将在 docker 引擎重新启动时尝试启动容器。我看到的例外情况是 docker 引擎本身未配置为在重新启动时自动启动(检查systemctl status docker 以确保它已启用)并且引擎在网络准备好之前启动容器,我只看到过覆盖网络。这两个都会破坏restart=always。
如果您希望即使没有用户执行登录也启动容器(例如我只启动并且不想每次登录的 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 命令替换为 docker-compose 命令,使用 -f 标志来指定 docker-compose 的位置文件:/usr/bin/docker-compose -f /path/to/docker-compose.yml up
docker-compose.yml 指定了.env 文件,请使用--project-directory /path/to 除了 明确指定您的docker compose 文件。
是的,docker 有restart policies,例如docker run --restart=always,可以处理这个问题。这也可以在compose.yml config file 中作为restart: always 使用。
【讨论】:
Systemd as service manager 是为此目的的最佳解决方案之一,需要更多的支持。
docker run --restart=always crmpicco-mysql,但出现错误:Unable to find image 'crmpicco-mysql:latest' locally。
docker run 命令需要您可以通过 docker images 列出的图像名称。