Looks good to me. What you want to understand when working on Docker policies is what each one means. always policy means that if it crashes for any reason automatically restart.
So if it stops for any reason, go ahead and restart it.
So why would you ever want to use always as opposed to say on-failure?
In some cases, you might have a container that you always want to ensure is running such as a web server. If you are running a public web application chances are you want that server to be available 100% of the time.
So for web application I expect you want to use always. On the other hand if you are running a worker process on a file and then naturally exit, that would be a good use case for the on-failure policy, because the worker container might be finished processing the file and you probably want to let it close out and not have it restart.
Thats where I would expect to use the on-failure policy. So not just knowing the syntax, but when to apply which policy and what each one means.
If you’re application is able to detect issues, you can easily have the container restart itself. The two important things are the --restart flag and that the application exists when it detects an issue.
Start the container in the background (-d) and set a restart policy:
docker run --restart unless-stopped -d [IMAGE] [COMMAND]
With the restart policy, you control what Docker does when the command exists. Using --restart unless-stopped tells Docker to always restart the command, no matter what the exit code of the command was. This way, you can have your application check its health, and if necessary use exit(1) or something similar to shutdown. When that happens, Docker will follow its restart policy and start a new container.
Although Docker doesn’t really care about the return code, I would make sure that the application exists with a status code other than 0 to indicate an issue. This might be useful later if you do want to analyze logs or use your container from scripts.
Edit:
I initially used --restart always in the answer, but after some consideration I think it might be better to use --restart unless-stopped here. Its behavior is more predictable, because docker stop does actually stop a service. With --restart always, docker stop will stop the container, but then start a new one again, which isn’t necessarily what you want or expect to happen.
If you’re application is able to detect issues, you can easily have the container restart itself. The two important things are the --restart flag and that the application exists when it detects an issue.
Start the container in the background (-d) and set a restart policy:
docker run --restart unless-stopped -d [IMAGE] [COMMAND]
With the restart policy, you control what Docker does when the command exists. Using --restart unless-stopped tells Docker to always restart the command, no matter what the exit code of the command was. This way, you can have your application check its health, and if necessary use exit(1) or something similar to shutdown. When that happens, Docker will follow its restart policy and start a new container.
Although Docker doesn’t really care about the return code, I would make sure that the application exists with a status code other than 0 to indicate an issue. This might be useful later if you do want to analyze logs or use your container from scripts.
Edit:
I initially used --restart always in the answer, but after some consideration I think it might be better to use --restart unless-stopped here. Its behavior is more predictable, because docker stop does actually stop a service. With --restart always, docker stop will stop the container, but then start a new one again, which isn’t necessarily what you want or expect to happen.
Получение уведомления о том, что контейнеры Docker не используются, является одним из худших способов провести ночь. В сегодняшней статье мы обсудим, как использовать политику перезапуска Docker для автоматического перезапуска контейнеров и предотвращения таких ночных уведомлений.
Что происходит при сбое приложения?
Прежде чем мы начнем с политики перезапуска Docker, давайте немного разберемся, как Docker ведет себя при сбое приложения. Чтобы облегчить это, мы создадим контейнер Docker, который выполняет простой сценарий bash с именем crash.sh .
|
1 2 3 |
|
Вышеприведенный скрипт прост; при запуске он будет sleep 30 секунд, а затем выйдет с кодом выхода 1 указывающим на ошибку.
Сборка и запуск пользовательского контейнера
Чтобы запустить этот скрипт в контейнере, нам нужно создать собственный контейнер Docker, который включает в crash.sh скрипт crash.sh . Чтобы создать собственный контейнер, нам сначала нужно создать простой Dockerfile .
Dockerfile будет содержать следующие три строки:
|
1 2 3 |
|
Приведенный выше Dockerfile создаст контейнер на основе последней версии ubuntu:14.04 . Он также добавит скрипт crash.sh в каталог / контейнера. Последняя строка сообщает Docker, что нужно запускать скрипт crash.sh при crash.sh контейнера.
Dockerfile , теперь мы можем собрать наш пользовательский контейнер с помощью команды docker build .
|
01 02 03 04 05 06 07 08 09 10 11 12 |
|
Эта команда построения создала образ Docker с testing_restarts именем testing_restarts . Теперь мы можем запустить контейнер, используя образ testing_restarts , выполнив testing_restarts docker run .
|
1 2 |
|
Из вышесказанного видно, что Docker смог запустить контейнер с именем testing_restarts . Давайте проверим состояние этого контейнера, запустив docker ps .
|
1 2 |
|
Команда docker ps не показывает никаких запущенных контейнеров. Причина этого заключается в том, что docker ps по умолчанию показывает только запущенные контейнеры. Давайте посмотрим на работающие и не работающие контейнеры, используя флаг -a .
|
1 2 3 |
|
С результатами docker ps мы видим, что при выходе из приложения в контейнере Docker этот контейнер также останавливается. Это означает, что по умолчанию, если приложение, работающее в контейнере, аварийно завершает работу, контейнер останавливается, и этот контейнер останется остановленным, пока кто-то или что-то не перезапустит его.
! Новый призыв к действию
Изменение поведения докера по умолчанию
Можно автоматически перезапустить разбитые контейнеры, указав политику перезапуска при запуске контейнера. Чтобы лучше понять политики перезапуска, давайте посмотрим, что происходит, когда мы используем политику перезапуска always с этим же контейнером.
|
1 2 |
|
В приведенной выше команде мы указали, что Docker должен применять политику always перезапуска к этому контейнеру с помощью флага --restart . Давайте посмотрим, как это повлияет на наш контейнер, выполнив docker ps снова.
|
1 2 3 |
|
На этот раз мы видим, что контейнер запущен и работает, но только в течение 21 секунды. Если мы снова запустим docker ps , мы увидим что-то интересное.
|
1 2 3 |
|
Второй запуск показывает, что контейнер был только в течение 19 секунд. Это означает, что даже если наше приложение ( crash.sh ) продолжает выходить с ошибкой, Docker постоянно перезапускает контейнер при каждом выходе.
Теперь, когда мы понимаем, как политики перезапуска могут использоваться для изменения поведения Docker по умолчанию, давайте посмотрим, какие политики перезапуска доступны в Docker.
Политика перезапуска докера
В настоящее время Docker имеет четыре политики перезапуска:
-
no -
on-failure -
unless-stopped -
always
Политика no является политикой перезапуска по умолчанию и просто не перезапускает контейнер ни при каких обстоятельствах.
Перезапуск при неудаче, но остановка при успехе
Политика on-failure немного интересна, поскольку она позволяет Docker перезапустить контейнер, если код завершения указывает на ошибку, но не если код выхода указывает на успех. Вы также можете указать максимальное количество раз, когда Docker автоматически перезапускает контейнер.
Давайте попробуем эту политику перезапуска с нашим контейнером testing_restarts и установим ограничение в 5 перезапусков.
|
1 2 |
|
Если мы запустим docker ps в течение минуты после запуска контейнера, мы увидим, что контейнер запущен и был недавно запущен.
|
1 2 3 |
|
Однако это не будет верно, если мы запустим команду docker ps 3 минуты после запуска контейнера.
|
1 2 3 |
|
Из вышесказанного видно, что через 3 минуты контейнер останавливается. Это связано с тем, что контейнер был перезапущен больше, чем наша настройка max-retries .
С успехом
Преимущество при on-failures состоит в том, что, когда приложение завершает работу с успешным кодом завершения, контейнер не будет перезапущен. Давайте посмотрим на это в действии, сделав небольшое изменение в скрипте crash.sh .
Изменением будет установка кода выхода на 0 .
|
1 2 3 |
|
Установив скрипт для выхода с кодом выхода 0 , мы удалим индикатор ошибки из скрипта. То есть, насколько Docker может сказать, этот скрипт будет успешно выполняться каждый раз.
С измененным сценарием нам нужно будет перестроить контейнер, прежде чем мы сможем запустить его снова.
|
01 02 03 04 05 06 07 08 09 10 11 12 |
|
С восстановлением образа контейнера, давайте снова запустим этот контейнер с теми же настройками при on-failures и max-retries .
|
1 2 |
|
На этот раз, когда мы выполняем docker ps -a , мы должны увидеть разные результаты.
|
1 2 3 |
|
Поскольку сценарий crash.sh с успешным кодом выхода ( 0 ), Docker воспринял это как успешное и не перезапустил контейнер.
Всегда перезапускать контейнер
Если мы хотим, чтобы контейнер перезапускался независимо от кода выхода, у нас есть пара политик перезапуска, которые мы могли бы использовать:
-
always -
unless-stopped
Политика always перезапуска говорит Docker перезапускать контейнер при любых обстоятельствах. Мы экспериментировали с политикой always перезапуска ранее, но давайте посмотрим, что произойдет, когда мы перезапустим текущий контейнер с политикой always перезапуска.
|
1 2 |
|
Если мы подождем несколько минут и снова запустим docker ps -a , мы увидим, что контейнер был перезапущен даже после успешного завершения кода завершения.
|
1 2 3 |
|
Что хорошо в политике always перезапуска, так это то, что даже если наш хост Docker потерпит крах при загрузке, служба Docker перезапустит наш контейнер. Давайте посмотрим на это в действии, чтобы полностью оценить, почему это полезно.
По умолчанию или даже при on-failures наш контейнер не будет работать при перезагрузке. Что, в зависимости от того, какую задачу выполняет контейнер, может быть проблематичным.
|
1 2 3 |
|
С политикой always перезапуска это не так. Политика always перезапуска всегда перезапускает контейнер. Это верно, даже если контейнер был остановлен перед перезагрузкой. Давайте посмотрим на этот сценарий в действии.
|
1 2 3 |
|
Перед перезагрузкой нашей системы мы просто остановили контейнер. Это означает, что контейнер все еще там, но не работает. Однако после перезагрузки системы контейнер будет работать.
|
1 2 3 |
|
Причиной запуска нашего контейнера после перезагрузки является политика always . При каждом перезапуске службы Docker контейнеры, использующие политику always будут перезапущены независимо от того, были они запущены или сейчас.
Проблема в том, что перезапуск контейнера, который был ранее остановлен после перезагрузки, может быть немного проблематичным. Что если наш контейнер был остановлен по уважительной причине или, что еще хуже, что если контейнер устарел?
Решением для этого является политика перезапуска без unless-stopped .
Останавливаться только когда остановлен Docker
Политика перезапуска без остановок ведет себя так же, как и always с одним исключением. Когда контейнер останавливается и сервер перезагружается или перезапускается служба Docker, контейнер перезапускаться не будет.
Давайте посмотрим на это в действии, запустив контейнер с политикой unless-stopped и повторив наш последний пример.
|
1 2 |
|
Запустив контейнер, давайте остановим его и снова перезагрузим систему.
|
1 2 3 |
|
На этот раз, когда система перезапустится, мы должны увидеть, что контейнер находится в остановленном состоянии.
|
1 2 3 |
|
Один из важных моментов с параметром ” unless-stopped заключается в том, что, если контейнер работал до перезагрузки, он будет перезапущен после перезапуска системы. Мы можем увидеть это в действии, перезапустив наш контейнер и перезагрузив систему снова.
|
1 2 3 |
|
После этой перезагрузки контейнер должен работать.
|
1 2 3 |
|
Разница между always и unless-stopped может быть небольшой, но в некоторых средах это небольшое различие может быть критическим решением.
Выбор лучшей политики перезапуска
При выборе наилучшей политики перезапуска важно помнить, какой тип рабочей нагрузки выполняет контейнер.
Например, экземпляр Redis может быть критическим компонентом в вашей среде, который должен иметь политику always или unless-stopped . С другой стороны, приложение пакетной обработки может нуждаться в перезапуске до успешного завершения процесса. В этом случае имеет смысл использовать политику при on-failures .
В любом случае, с помощью политики перезапуска Docker вы можете быть уверены, что в следующий раз, когда хост Docker загадочно перезагрузится в 3 часа ночи, ваши контейнеры будут перезапущены.