Как я могу автоматически перезапустить свои контейнеры Docker с помощью автоматического удаления контейнера?

У меня есть VPS общего назначения, и я настраиваю приложения на нем. На нем будет около 5-6 контейнеров и очень мало чего еще, так что ящик можно тривиально перестроить по мере необходимости.

Для каждого приложения у меня есть сценарий запуска. Контейнер WordPress выглядит следующим образом:

#!/bin/bash# Get the host IP addressexport 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 заключается в том, что во время процесса докеризации я останавливаю текущий запущенный контейнер, load новую версию изображения и повторно запустите приведенный выше скрипт. Это означает, что Docker получает уведомление о restart политика для каждого контейнера. Я обнаружил, что после перезагрузки коробки у меня будет 15 или около того слегка отличающихся версий приложения, запущенных одновременно, что не входит в мои намерения.

Я полагаю, я мог бы использовать docker update --restart never на старых контейнерах, чтобы этого не происходило, но затем, когда мой контейнер останавливается, он остается лежать без дела, и я бы с таким же успехом удалил его автоматически. Я мог бы периодически очищать старые, используя какое-то задание cron, но это кажется немного халтурным, учитывая, что Docker может сделать это за меня.

В поисках целого ряда ответов

Очень полезный комментарий подсказал мне, что я должен изучить Minikube, который, по-видимому, упрощает настройку Kubernetes, даже до такой степени, что достаточно квалифицированный специалист может быть запущен и запущен за пять минут.

Я все еще очень хотел бы видеть предложенные более легкие решения, поэтому у меня есть целый ряд ответов на выбор. Как уже указывалось, я хотел бы узнать ответ на вопрос, будет ли работать такой супервайзер процессов, как Monit.

Навскидку, я мог бы написать цикл оболочки для записи docker ps в файл каждые пять секунд в течение минуты, а затем запускайте его в Cron каждую минуту. Затем я мог бы отсканировать этот файл с помощью grep и Монит CHECK PROGRAM проверка системы. Это немного банально, но это то, что я могу легко понять, если с этим возникнут проблемы. Есть какие-нибудь подвижки в этом предложении?

У меня есть ответ, который подходит для моего нынешнего понимания Docker. В комментариях мне посоветовали попробовать Minikube, и хотя, несомненно, это можно быстро раскрутить, я боялся, что это будет кроличья нора обучения, из-за которой я застряну в tar на несколько недель. Один из моих инженерных принципов - знать, когда человек достиг когнитивного предела для вброса новой информации!

Таким образом, я решил решить эту проблему простым способом. У меня было два варианта:

  1. Используйте функцию автоматического удаления контейнера в Docker и настройте мою собственную систему перезапуска
  2. Используйте политику перезапуска Docker и настройте мою собственную систему удаления контейнеров

Я начал с первого из них с идеи, что было бы неплохо использовать process supervisor Monit, отчасти потому, что он легкий, а отчасти потому, что я с ним знаком. Тем не менее, это начало казаться неправильным решением, поскольку я бы работал над основной проблемой, заключающейся в том, что он не может чисто получить список процессов контейнера Docker.

На самом деле, второй вариант был намного чище, и это усиливалось тем фактом, что очистка контейнера на самом деле не является приоритетом - это просто поддержание порядка. Конечно, я использовал для этого Docker; вот Dockerfile:

# Docker build script for Docker TidyFROM alpine:3.6RUN apk updateRUN apk add docker# See this for BusyBox cron schedules# https://gist.github.com/andyshinn/3ae01fa13cb64c9d36e7COPY bin/docker-tidy.sh /etc/periodic/daily/RUN chmod +x /etc/periodic/daily/docker-tidy.sh# Start Cron in the foregroundENTRYPOINT ["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 containersCONTAINER_LABEL=docker-tidy-instancedocker ps --all --filter label=$CONTAINER_LABEL --quiet | xargs --no-run-if-empty docker update --restart nodocker run \    --label $CONTAINER_LABEL \    --volume /var/run/docker.sock:/var/run/docker.sock \    --detach \    --restart always \    docker-tidy

Иди поиграй с Миникубом, ты сможешь сделать это примерно за пять минут.

Достаточно справедливо, @Michael. Могу ли я сделать это с помощью Monit (на основании того, что я немного знаком с ним)? Я посмотрел на справочную страницу, но это чудовищное чтение, и я потерял волю к жизни, когда пробирался через это. Однако мне интересно, судя по документам, является ли проверка программы будет работать - если я смогу ввести параметр в путь к исполняемому файлу, он может вернуть успех / сбой в зависимости от того, запущен ли именованный контейнер.

Вероятно, есть более ориентированный на Docker способ сделать это, но мой поисковый запрос не выявил ничего особенно интересного.

Честно говоря, если вы так часто перестраиваете контейнеры, вам следует использовать что-то вроде Kubernetes для управления вещами.

Ты прав, @Michael, и я углублюсь в это, когда у меня будет время. Субподрядчик Docker на Reddit сообщил мне, что Kube - довольно сложное предприятие (хотя и ценное). Сейчас я поищу что-нибудь попроще, что у меня есть шанс грокнуть.

(В комментарии здесь пять минут назад, который теперь удален, говорилось, что мне просто нужно “перезагрузиться”. Да, это сработало бы, но тогда мне пришлось бы отказаться от --rm - у меня может быть одно или другое, но не оба, учитывая ошибку, которую я показал в вопросе. Смотрите поясняющую правку о том, почему я думаю, что требуется --rm).

Нет хорошего способа провести различие между обстоятельствами, когда вы хотите перезапустить контейнер, и обстоятельствами, когда вы хотите удалить контейнер. Это то, с чем вам нужно справиться самостоятельно за пределами Docker.