Docker

如何使用容器自動刪除功能自動重啟我的 Docker 容器?

  • April 11, 2018

我有一個通用 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

但是,這會返回一個錯誤:

衝突的選項:–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系統檢查來掃描該文件。這有點駭人聽聞,但如果它有問題,我可以很容易地理解它。這個建議有什麼進展嗎?

我有一個適合我目前對 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"]

這是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

引用自:https://serverfault.com/questions/905988