Docker предоставляет параметр политики перезапуска, позволяющий автоматически перезапускать контейнеры в случае определенных событий или сбоев.
Это чрезвычайно полезно в сценариях, когда вам необходимо перезапустить хост Docker (ваш сервер Linux) или если служба, работающая в контейнере, не работает.
Политики перезапуска Docker применяются для каждого контейнера. Есть два способа назначить контейнеру политику перезапуска. Вы можете установить его в файле YAML, если собираетесь использовать Docker Compose, Swarm или Kubernetes.
Вы также можете установить политику перезапуска прямо в командной строке при запуске контейнера:
docker container run --restart <policy>
Давайте поговорим о том, какую политику перезапуска вы можете использовать.
Политики перезапуска докеров
Существуют следующие политики перезапуска контейнеров Docker:
- no: по умолчанию контейнеры не запускаются автоматически.
- always: всегда перезапускать остановленный контейнер, если контейнер не был остановлен явно
- unless-stopped: перезапустить контейнер, если контейнер не был в остановленном состоянии до остановки демона Docker (объяснено позже).
- on-failure: перезапустите контейнер, если он завершился с ненулевым кодом выхода или если демон докера перезапустился.
Как мы уже упоминали, если вы явно не добавите политику перезапуска, она будет иметь значение «no», что означает, что контейнеры не будут перезапущены автоматически.
Объяснение политик перезапуска Docker на примерах
Позвольте нам показать эти политики в действии, чтобы вы могли их реально визуализировать. Это особенно полезно для понимания разницы между политикой always и unless-stopped.
Политика перезапуска always
Начнем с политики перезапуска always. Если эта политика установлена, контейнер всегда будет перезапускаться, если он не был остановлен явно.
Мы собираемся запустить контейнер Alpine Linux с политикой перезапуска always. Мы называем это всегда политикой.
У контейнера одна задача. Он запускает команду sleep в bash в течение 10 секунд, а затем завершает работу.
docker container run --name always-policy --restart always alpine sleep 10
Без политики перезапуска always контейнер остановился бы через 10 секунд. Но здесь он автоматически перезапустится и запустит команду сна еще 10 секунд, и так будет продолжаться.
destroyer@andreyex:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1171dcfb7e06 alpine "sleep 10" 25 seconds ago Up 4 seconds always-policy
В приведенной выше команде вы можете видеть, что, хотя контейнер был создан 25 секунд назад, он работал всего 4 секунды. Учтите, что тот же контейнер перезапускается, новый не создается.
Вы можете использовать команду docker inspect, чтобы узнать, сколько раз контейнер был перезапущен на данный момент.
destroyer@andreyex:~$ docker inspect always-policy | grep -i restartcount "RestartCount": 4,
Если вы остановите контейнер с помощью команды остановки, он не перезапустится автоматически после этого. В приведенном ниже примере вы можете увидеть, что контейнер теперь имеет статус «Exited», а не «Up».
destroyer@andreyex:~$ docker stop always-policy always-policy destroyer@andreyex:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1171dcfb7e06 alpine "sleep 10" 58 seconds ago Exited (0) 6 seconds ago always-policy
Мы использовали вариант -it запуска контейнера с интерактивным терминалом на скриншоте выше. Это было по привычке и здесь не нужно.
Политика перезапуска unless-stopped vs always
unless-stopped похоже на политику перезагрузки always. Оба перезапускают контейнеры автоматически, и если вы остановите контейнеры явно, они не перезапустятся.
Но основное различие между ними заключается в том, что если вы остановите контейнеры с помощью команды docker stop, а затем перезапустите демон docker, контейнер с политикой перезапуска always запустит контейнер автоматически, но контейнер с политикой unless-stopped не будет перезапущен.
Покажу это на примерах. У меня уже есть остановленный контейнер с политикой постоянного перезапуска. Позвольте мне создать новый контейнер с именем except-stop-policy с политикой unless-stopped.
docker container run --name unless-stopped-policy --restart always alpine sleep 10
Остановите контейнер:
docker stop unless-stopped-policy
Теперь у нас есть два контейнера, которые явно остановлены:
destroyer@andreyex:~$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d244b6e08899 alpine "sleep 10" 2 minutes ago Exited (0) About a minute ago unless-stopped-policy 1171dcfb7e06 alpine "sleep 10" 22 minutes ago Exited (0) 21 minutes ago always-policy
Перезапустите демон Docker:
sudo systemctl restart docker
Теперь, если вы проверите запущенные контейнеры, вы увидите, что контейнер с именем always-policy работает, потому что он был установлен с политикой перезапуска always.
destroyer@andreyex:~$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1171dcfb7e06 alpine "sleep 10" 30 minutes ago Up 8 seconds always-policy
Политика перезапуска on-failure
Политика перезапуска on-failure перезапускает контейнер, если он был завершен с ненулевым кодом выхода (указывающим на ошибку/сбой). Он также перезапускает контейнеры, если перезапускается демон docker, включая те, которые ранее находились в остановленном состоянии.
Если вы вручную остановите контейнер с помощью команды docker stop, он будет существовать с нулевым кодом, указывающим, что все было нормально.
Настройка политики перезапуска в файле Docker Compose
К настоящему времени у вас есть довольно хорошее представление о запуске контейнера с политикой перезапуска.
Если вы используете что-то вроде Docker Compose для развертывания контейнеров, вы можете упомянуть политику перезапуска для объекта службы в файле YAML.
Вот пример:
version: "3.3" services: NginxProxy: image: "jwilder/nginx-proxy:latest" restart: "on-failure" networks: ["net"] ports: - "80:80" - "443:443"
Какую политику перезапуска Docker использовать?
Честно говоря, однозначного ответа на этот вопрос нет. Это зависит от вашего варианта использования и того, что вы хотите.
Надеюсь, эта статья была полезна для понимания политики перезапуска Docker. Если у вас есть какие-либо вопросы или предложения, дайте мне знать в разделе комментариев.