Политики перезапуска контейнеров Docker
Практическая настройка restart policy в Docker и Docker Compose: no, always, unless-stopped, on-failure и проверка поведения контейнеров.
Контейнер может завершиться из-за ошибки приложения, перезапуска Docker daemon или перезагрузки сервера. Политика перезапуска определяет, должен ли Docker автоматически запустить такой контейнер снова.
В этой инструкции рассматриваются только restart policy в Docker и Docker Compose: доступные режимы, настройка, проверка и типичные ошибки.
Проверено на: Ubuntu Server 24.04 LTS и Docker Engine
Уровень сложности: начальный
Время выполнения: около 15 минут
Требуемый доступ: пользователь с доступом к Docker
Что будет рассмотрено
После выполнения инструкции можно будет:
- выбрать подходящую политику перезапуска;
- настроить её через
docker run; - использовать restart policy в Docker Compose;
- изменить политику существующего контейнера;
- проверить автоматический запуск после сбоя;
- отличать
alwaysотunless-stopped; - диагностировать контейнеры, которые постоянно перезапускаются.
Доступные политики
Docker поддерживает четыре основных режима:
no
on-failure
always
unless-stopped
no
Автоматический перезапуск отключён.
Это поведение используется по умолчанию.
no
Подходит для:
- разовых задач;
- тестовых контейнеров;
- ручного запуска;
- команд, которые должны завершиться после выполнения.
on-failure
Контейнер перезапускается только при завершении с ненулевым кодом.
on-failure
Можно ограничить количество попыток:
on-failure:5
Подходит для:
- batch-задач;
- обработчиков очередей;
- сервисов, где необходимо ограничить число повторных запусков.
always
Docker пытается запускать контейнер всегда:
- после аварийного завершения;
- после перезапуска Docker daemon;
- после перезагрузки сервера;
- после ручной остановки контейнер останется остановленным только до перезапуска Docker daemon.
unless-stopped
Контейнер автоматически запускается:
- после сбоя;
- после перезапуска Docker daemon;
- после перезагрузки сервера.
Но если контейнер был остановлен вручную, Docker не запускает его снова автоматически.
Для большинства постоянных сервисов это наиболее предсказуемый вариант.
Проверка текущей политики
Для конкретного контейнера:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Полный объект:
docker inspect --format '{{json .HostConfig.RestartPolicy}}' CONTAINER_NAME
Пример результата:
{"Name":"unless-stopped","MaximumRetryCount":0}
Запуск контейнера без автоперезапуска
docker run -d --name restart-no --restart no nginx:alpine
Проверьте:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' restart-no
Ожидаемый результат:
no
Настройка unless-stopped
docker run -d --name restart-unless-stopped --restart unless-stopped nginx:alpine
Проверьте:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' restart-unless-stopped
Настройка always
docker run -d --name restart-always --restart always nginx:alpine
Проверьте:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' restart-always
Настройка on-failure
Создайте контейнер, который завершится с ошибкой:
docker run -d --name restart-on-failure --restart on-failure:3 alpine sh -c 'exit 1'
Проверьте состояние:
docker ps -a --filter name=restart-on-failure
Посмотрите количество перезапусков:
docker inspect --format '{{.RestartCount}}' restart-on-failure
Ожидается не более трёх повторных запусков.
Код завершения контейнера
Проверить код завершения:
docker inspect --format '{{.State.ExitCode}}' CONTAINER_NAME
Значение:
0
означает штатное завершение.
Ненулевое значение означает ошибку и может активировать политику on-failure.
Использование в Docker Compose
Пример:
services:
web:
image: nginx:alpine
restart: unless-stopped
ports:
- "8080:80"
Проверьте конфигурацию:
docker compose config
Запустите:
docker compose up -d
Проверьте политику:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Пример с on-failure в Compose
services:
worker:
image: alpine
command:
- sh
- -c
- exit 1
restart: on-failure:5
Проверьте:
docker compose up -d
Посмотрите состояние:
docker compose ps -a
Изменение политики существующего контейнера
Политику можно изменить без пересоздания:
docker update --restart unless-stopped CONTAINER_NAME
Проверьте:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Отключить автоперезапуск:
docker update --restart no CONTAINER_NAME
Проверка поведения после сбоя
Запустите контейнер:
docker run -d --name restart-test --restart unless-stopped alpine sh -c 'while true; do sleep 3600; done'
Проверьте PID основного процесса:
docker inspect --format '{{.State.Pid}}' restart-test
Завершите процесс внутри контейнера:
docker exec restart-test sh -c 'kill 1'
Подождите несколько секунд и проверьте:
docker ps --filter name=restart-test
Посмотрите количество перезапусков:
docker inspect --format '{{.RestartCount}}' restart-test
Проверка после перезапуска Docker daemon
Проверьте исходное состояние:
docker ps
Перезапустите Docker:
sudo systemctl restart docker
Проверьте контейнеры:
docker ps
Контейнеры с always и unless-stopped должны снова запуститься, если они не были остановлены вручную.
Проверка после перезагрузки сервера
Перед перезагрузкой:
docker ps --format 'table {{.Names}} {{.Status}}'
Перезагрузите сервер:
sudo reboot
После входа:
docker ps --format 'table {{.Names}} {{.Status}}'
Проверьте политику:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Разница между always и unless-stopped
Рассмотрим ручную остановку:
docker stop CONTAINER_NAME
Для unless-stopped:
- контейнер останется остановленным;
- не будет автоматически запущен после перезапуска Docker daemon.
Для always:
- после ручной остановки контейнер не запускается немедленно;
- после следующего перезапуска Docker daemon он может быть запущен снова.
Поэтому для обычных постоянных сервисов часто выбирают:
unless-stopped
Что restart policy не делает
Политика перезапуска не заменяет:
- healthcheck;
- мониторинг;
- исправление причины сбоя;
- ограничение ресурсов;
- сбор логов;
- резервное копирование.
Контейнер может иметь статус running, но приложение внутри него может быть неисправно.
Постоянный restart loop
Если процесс сразу завершается, контейнер может постоянно перезапускаться.
Проверьте:
docker ps -a
Посмотрите статус:
docker inspect --format '{{.State.Status}} {{.State.ExitCode}} {{.RestartCount}}' CONTAINER_NAME
Посмотрите логи:
docker logs --tail 100 CONTAINER_NAME
Для Compose:
docker compose logs --tail=100 SERVICE_NAME
Временное отключение restart loop
Отключите политику:
docker update --restart no CONTAINER_NAME
Остановите контейнер:
docker stop CONTAINER_NAME
После исправления конфигурации верните политику:
docker update --restart unless-stopped CONTAINER_NAME
Пересоздание контейнера через Compose
Если политика изменена в compose.yaml, примените:
docker compose up -d
Для гарантированного пересоздания:
docker compose up -d --force-recreate
Проверьте:
docker compose ps
Проверка всех контейнеров
Вывести имена и политики:
for container in $(docker ps -aq); do
docker inspect --format '{{.Name}} {{.HostConfig.RestartPolicy.Name}}' "$container"
done
Убрать начальный символ /:
for container in $(docker ps -aq); do
docker inspect --format '{{trimPrefix "/" .Name}} {{.HostConfig.RestartPolicy.Name}}' "$container"
done
Если установлен jq, можно использовать:
docker inspect $(docker ps -aq) |
jq -r '.[] |
[.Name[1:], .HostConfig.RestartPolicy.Name] |
@tsv'
Рекомендуемый выбор
Для постоянного веб-сервиса:
restart: unless-stopped
Для worker с ограничением попыток:
restart: on-failure:5
Для разовой команды:
restart: "no"
Для системного сервиса, который должен запускаться после каждого перезапуска Docker daemon:
restart: always
Почему no лучше брать в кавычки в YAML
В YAML значение:
restart: no
может быть интерпретировано как логическое значение.
Безопасный вариант:
restart: "no"
Типичные проблемы
Контейнер не запускается после перезагрузки
Проверьте политику:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Проверьте Docker:
systemctl status docker --no-pager
Проверьте журнал:
sudo journalctl -u docker -b --no-pager
unless-stopped не запустил контейнер
Возможно, контейнер был остановлен вручную до перезагрузки.
Запустите его:
docker start CONTAINER_NAME
Контейнер постоянно перезапускается
Проверьте:
docker logs --tail 100 CONTAINER_NAME
Отключите restart policy на время диагностики:
docker update --restart no CONTAINER_NAME
on-failure не перезапускает контейнер
Проверьте код завершения:
docker inspect --format '{{.State.ExitCode}}' CONTAINER_NAME
Если код равен 0, завершение считается успешным.
Изменения Compose не применились
Проверьте итоговую конфигурацию:
docker compose config
Пересоздайте контейнер:
docker compose up -d --force-recreate
Быстрый набор команд
Проверить политику:
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' CONTAINER_NAME
Изменить на unless-stopped:
docker update --restart unless-stopped CONTAINER_NAME
Отключить:
docker update --restart no CONTAINER_NAME
Проверить число перезапусков:
docker inspect --format '{{.RestartCount}}' CONTAINER_NAME
Посмотреть логи:
docker logs --tail 100 CONTAINER_NAME
Удаление тестовых контейнеров
docker rm -f restart-no restart-unless-stopped restart-always restart-on-failure restart-test 2>/dev/null
Итог
После выполнения инструкции:
- рассмотрены все основные restart policy;
- настроены
no,on-failure,alwaysиunless-stopped; - проверено поведение после сбоя;
- изменена политика существующего контейнера;
- показано использование в Docker Compose;
- разобран постоянный цикл перезапуска;
- объяснена разница между
alwaysиunless-stopped.
Для большинства постоянно работающих контейнеров разумным базовым выбором является unless-stopped, но окончательная политика зависит от назначения сервиса.