Назад | Перейти на главную страницу

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

У меня есть VPS общего назначения, и я докерирую приложения на нем. На нем будет около 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.

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

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

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

  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