我有一个通用 VPS,正在 Docker 化上面的应用程序。上面大约有 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
但是,这会返回一个错误:
冲突的选项:--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"
但是,这会检查系统进程表,而不是docker ps
,因此它找不到与指定字符串匹配的内容。我可以让它docker ps
定期执行,并匹配输出中的行吗?
如果其他工具足够强大,我很乐意使用它。例如,我发现 Supervisor 有点重,但如果它更适合与 Docker 配合使用,我愿意使用它。
关于 --rm 的澄清
我想要的原因--rm
是,在 Dockerisation 过程中,我停止当前正在运行的容器、load
新版本的映像,然后重新运行上述脚本。这意味着 Docker 会收到restart
有关每个容器的策略的通知。我发现,重新启动机器后,我会同时运行 15 个左右略有不同的应用程序版本,这不是我想要的。
我想我可以docker update --restart never
在旧容器上使用以防止这种情况发生,但是当我的容器停止时,它就被留在我身边,我很快就会让它自动删除。我可以使用某种 cron 作业定期清理旧容器,但考虑到 Docker 可以帮我做这件事,这感觉有点不合时宜。
寻求一系列答案
一个非常有用的评论建议我应该研究一下 Minikube,它显然简化了 Kubernetes 的设置,甚至一个具有适当技能的人可以在五分钟内启动并运行。
我仍然非常希望看到更多轻量级解决方案被提出,所以我有一系列的答案可供选择。正如所指出的,我想知道像 Monit 这样的流程监控器是否可行。
我首先想到的是,我可以编写一个 shell 循环,docker ps
每五秒写入一个文件,持续一分钟,然后每分钟在 Cron 上运行一次。然后我可以使用grep
MonitCHECK PROGRAM
系统检查来扫描该文件。这有点不合时宜,但如果出现问题,我可以轻松理解。这个建议有什么进展吗?
答案1
我有一个适合我目前对 Docker 理解的答案。评论中建议我尝试 Minikube,虽然毫无疑问它可以快速启动,但我担心这将是一个学习的兔子洞,会让我在 tar 中呆上几个星期。我的工程原则之一是知道一个人何时达到了塞入新信息的认知极限!
因此,我开始用一种简单的方式解决这个问题。我有两个选择:
- 使用 Docker 中的容器自动删除功能,并设置我自己的重启系统
- 使用 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"]
下面是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)
最后,我的解决方案的一个缺点是,如果在停止的容器清理之前重新启动主机,这些容器似乎也会重新启动。因此,我在启动新容器之前重置了这些容器的重启策略。
例如,下面是我在主机上启动 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