如何使用容器自动删除功能自动重启我的 Docker 容器?

hal*_*fer 6 monit docker

我有一个通用的 VPS,并且正在对它的应用程序进行 Dockerising。上面将有大约 5-6 个容器,其他很少,因此可以根据需要对盒子进行简单的重建。

对于每个应用程序,我都有一个启动脚本。WordPress 容器如下所示:

#!/bin/bash

# Get the host IP address
export DOCKER_HOSTIP=`ifconfig docker0 | grep "inet addr" | cut -d ':' -f 2 | cut -d ' ' -f 1`
echo "Connecting to database on Docker host ${DOCKER_HOSTIP}"

docker run \
    --add-host=docker:${DOCKER_HOSTIP} \
    --network dockernet \
    --network-alias jonblog \
    --detach \
    --restart always \
    --rm \
    jonblog
Run Code Online (Sandbox Code Playgroud)

但是,这会返回错误:

冲突选项:--restart 和--rm

有几张 Docker 票说这是明智的,但我不明白。我想我的意思很明确:如果一个容器没有运行(例如在启动时),那么我想启动它。如果它死了,那么我希望容器被删除,并从基础映像创建一个新的容器。无论如何,容器应该是不可变的——我希望保留的任何状态,如媒体文件和日志,都将被写入卷。

所以,我想我应该放弃这个--restart标志,然后使用进程管理器来停止和启动 Docker 容器。我可以在这里使用Monit吗?我希望能够做这样的事情:

CHECK PROCESS jonblog MATCHING jonblog
  START PROGRAM = "/root/docker/jonblog/host-start.sh"
  STOP PROGRAM = "docker stop jon-blog"
Run Code Online (Sandbox Code Playgroud)

但是,它会检查系统进程表,而不是docker ps,因此它不会找到与指定字符串匹配的内容。我可以让它docker ps定期执行,并匹配输出中的行吗?

如果它被证明是健壮的,我很乐意使用另一个工具。比如我觉得Supervisor有点重量级,但是如果那个更能和Docker一起工作,我愿意用它。

澄清--rm

我想要的原因--rm是在 Dockerisation 过程中,我停止当前正在运行的容器,load一个新版本的镜像,并重新运行上面的脚本。这意味着 Docker 会收到restart每个容器的策略通知。我发现在重新启动盒子后,我会同时运行 15 个左右略有不同的应用程序版本,这不是我们的意图。

我想我可以docker update --restart never在旧容器上使用来防止这种情况发生,但是当我的容器停止时,我会留下它,我会尽快让它自动删除。我可以使用某种 cron 作业定期清理旧的,但考虑到 Docker 可以为我做这件事,这感觉有点麻烦。

寻求一系列答案

一个非常有用的评论建议我应该研究 Minikube,它显然简化了 Kubernetes 的设置,甚至可以在一定程度上简化 Kubernetes 的熟练程度,甚至可以在 5 分钟内启动并运行。

我仍然很希望看到更多轻量级的解决方案被提出,所以我有一系列的答案可供选择。如上所述,我想找出像 Monit 这样的流程主管是否可行的答案。

在我的头脑中,我可以编写一个 shell 循环,docker ps每五秒写入一个文件,持续一分钟,然后每分钟在 Cron 上运行它。然后我可以使用grepMonitCHECK PROGRAM系统检查扫描该文件。这有点hacky,但如果有问题,我可以轻松理解。该建议有任何进展吗?

hal*_*fer 1

我有一个适合我目前对Docker的理解的答案。评论中建议我尝试 Minikube,尽管毫无疑问这可以快速启动,但我担心这将是一个学习的兔子洞,会让我在 tar 中陷入困境。我的工程原则之一是知道一个人何时达到了填充新信息的认知极限!

因此,我开始以简单的方式解决这个问题。我有两个选择:

  1. 使用Docker中的容器自动删除功能,并设置我自己的重启系统
  2. 使用Docker重启策略,搭建我自己的容器删除系统

我从第一个开始,认为进程管理器 Monit 会很好用,部分是因为它是轻量级的,部分是因为我对它很熟悉。然而,它开始感觉像是一个错误的解决方案,因为我要解决核心问题,即它无法干净地获取 Docker 容器进程列表。

事实上,第二个选项更干净,并且由于停止容器清理实际上并不是优先事项 - 它只是为了保持整洁而放大了这一点。当然,我为此使用了 Docker;这是Dockerfile

# Docker build script for Docker Tidy

FROM alpine:3.6

RUN apk update
RUN apk add docker

# See this for BusyBox cron schedules
# https://gist.github.com/andyshinn/3ae01fa13cb64c9d36e7
COPY bin/docker-tidy.sh /etc/periodic/daily/
RUN chmod +x /etc/periodic/daily/docker-tidy.sh

# Start Cron in the foreground
ENTRYPOINT ["crond", "-l", "2", "-f"]
Run Code Online (Sandbox Code Playgroud)

这是bin/docker-tidy.sh

#!/bin/sh
#
# With thanks to:
# http://www.doublecloud.org/2015/05/simple-script-to-list-and-remove-all-stopped-docker-containers/

docker rm -v $(docker ps -a -q -f status=exited)
Run Code Online (Sandbox Code Playgroud)

最后,我的解决方案的一个缺点是,如果在停止的容器清理之前重新启动主机,那么这些容器似乎也会重新启动。因此,在启动新容器之前,我重置了这些容器的重启策略。

例如,以下是我在主机上启动 Docker Tidy 容器本身的方法。在实践中,我已将策略更改代码整理到自己的脚本中,但这将给出总体思路:

#!/bin/bash

# Removes the restart policy from previous containers
CONTAINER_LABEL=docker-tidy-instance
docker ps --all --filter label=$CONTAINER_LABEL --quiet | xargs --no-run-if-empty docker update --restart no

docker run \
    --label $CONTAINER_LABEL \
    --volume /var/run/docker.sock:/var/run/docker.sock \
    --detach \
    --restart always \
    docker-tidy
Run Code Online (Sandbox Code Playgroud)