Краткий ответ
Когда Docker контейнер сразу завершается, сначала проверьте `docker logs` и код выхода. Самые частые причины: неверная команда запуска, приложение, которое сразу завершается, отсутствующая конфигурация или разрешение, и контейнер, которому нечего делать в основном процессе. Исправьте команду или entrypoint и запустите контейнер интерактивно, чтобы увидеть ошибку.
Как проявляется проблема
- `docker ps` не показывает контейнер, а `docker ps -a` отображает его как Exited
- Контейнер запускается и исчезает в течение нескольких секунд
- В логах ничего нет или только сообщение об ошибке при запуске
- Приложение работает локально, но в контейнере сразу завершается
- Код выхода 0, 1, 127 или 137
Частые причины
Неверная команда запуска или entrypoint
Если в Dockerfile или команде `docker run` указана несуществующая команда, контейнер завершается с кодом 127. Проверьте, правильный ли путь к исполняемому файлу и соответствует ли команда формату, который ожидает Docker.
Приложение сразу завершается
Контейнер живёт до тех пор, пока работает основной процесс. Если приложение просто что-то делает и завершается или запущено в фоне, контейнер завершится. Нужно, чтобы основной процесс оставался на переднем плане.
Отсутствует конфигурация или разрешение
Приложение может упасть, если нет переменных окружения, файла конфигурации или разрешения на запись. В логах тогда видна ошибка при запуске, например, что база данных недоступна или файл не существует.
Порт или ресурсы
Если порт занят, запуск может не удаться с сообщением, что порт уже используется. Контейнер может завершиться и при недостатке памяти или если процесс был убит из-за ограничений.
Зависимость между сервисами
В окружении Docker Compose контейнер может не запуститься или завершиться, если сервис, от которого он зависит, не готов. Проверьте порядок и условия в `depends_on`, а healthcheck используйте, чтобы проверить, действительно ли зависимый сервис готов.
Пошаговое решение
- 1
Проверьте статус и код выхода
Выполните
docker ps -a, чтобы увидеть все контейнеры, включая остановленные. Обратите внимание на столбец STATUS и код выхода. Код 0 означает, что процесс завершился нормально, 1 - общая ошибка, 127 - несуществующая команда, а 137 указывает на принудительную остановку, часто из-за памяти. - 2
Просмотрите логи
Выполните
docker logs <имя_или_id>. Если контейнер остановлен, добавьте--tail 100, чтобы увидеть последние сто строк. Логи чаще всего содержат точную причину, например, ошибку в конфигурации или сообщение, что команда не найдена. - 3
Запустите контейнер интерактивно
Обойдите команду запуска и войдите в оболочку:
docker run -it --entrypoint /bin/sh <образ>. Если в образе нетsh, попробуйтеbash. Внутри контейнера вручную запустите приложение и увидите ошибку, которую обычно не видно. - 4
Проверьте команду и entrypoint
Посмотрите Dockerfile и команду
docker run. Убедитесь, чтоCMDилиENTRYPOINTв правильном формате и что путь к исполняемому файлу существует. Если используетеdocker compose, проверьте полеcommandвdocker-compose.yml. - 5
Убедитесь, что основной процесс остаётся на переднем плане
Приложение не должно запускаться в фоне или сразу завершаться. Если это скрипт, добавьте в конец цикл или запустите сервер, который слушает. Для контейнеров, которые должны просто оставаться активными, используйте
tail -f /dev/nullкак временное решение. - 6
Проверьте переменные окружения и конфигурацию
Сравните
docker inspect <контейнер>с тем, что ожидает приложение. Отсутствующие переменные добавьте через-eили в секцииenvironment. Проверьте также, что файлы конфигурации смонтированы по правильному пути. - 7
Проверьте разрешения и владельца
Если приложение пишет в том или папку, убедитесь, что пользователь внутри контейнера имеет разрешение. В
docker runдобавьте--userили настройте Dockerfile. Ошибки с разрешениями часто видны в логах какPermission denied. - 8
Отключите healthcheck и зависимости
Если используете Compose, временно закомментируйте
healthcheckиdepends_on, чтобы увидеть, работает ли контейнер самостоятельно. Затем возвращайте их по одному и наблюдайте за поведением. - 9
Пересоберите образ
Если вы меняли Dockerfile, выполните
docker build --no-cache -t <имя> .и снова запустите контейнер. Кэшированный слой может скрыть изменение, которое является причиной проблемы.
Если ничего не помогает
Включите более подробное логирование приложения и запустите его с docker run без -d, чтобы видеть вывод в реальном времени. Проверьте, не завершается ли контейнер из-за OOMKilled в docker inspect (поле State.OOMKilled). Если используете Kubernetes или другой оркестратор, посмотрите события и количество перезапусков. Когда проблема в самом приложении, запустите его вне контейнера с теми же переменными окружения, чтобы изолировать Docker. Для сложных случаев с несколькими сервисами полезно создать минимальный docker-compose.yml только с одним сервисом и постепенно добавлять остальные.
Как избежать повторения
- Всегда используйте `docker logs` и код выхода, прежде чем что-либо менять.
- В Dockerfile явно указывайте `CMD` или `ENTRYPOINT` и тестируйте его локально.
- Периодически очищайте остановленные контейнеры, неиспользуемые сети и висячие образы командой `docker system prune`; перед запуском проверьте, что будет удалено, и сделайте резервную копию важных данных.
- В файле Compose определите healthcheck и `restart: unless-stopped` для сервисов, которые должны работать постоянно.
Когда лучше обратиться к специалисту
Если вы испробовали все шаги, а контейнер всё ещё завершается без ясной причины, или если проблема затрагивает несколько сервисов и производственную среду, обратитесь в ИТ-поддержку, чтобы вместе проанализировать конфигурацию и логи.
Разработка ПО и продуктов · Приложения на заказ, SaaS и MVP за 4-8 недельЧастые вопросы
Почему контейнер завершается с кодом выхода 0?
Код выхода 0 означает, что основной процесс завершился успешно, но это также значит, что контейнеру больше нечего делать. Чаще всего приложение было запущено в фоне или завершилось сразу. Решение в том, чтобы основной процесс оставался на переднем плане.
Как увидеть ошибку, которая не появляется в логах?
Запустите контейнер интерактивно с `docker run -it --entrypoint /bin/sh <образ>` и вручную запустите приложение. Так вы увидите вывод в реальном времени. Можно также временно запустить контейнер с командой `sleep 3600`, при необходимости с `--entrypoint`, затем войти в него и тестировать.
Что означает код выхода 137?
Код 137 обычно означает, что процесс был принудительно прерван, чаще всего из-за нехватки памяти (OOM). Проверьте `docker inspect` и поле `State.OOMKilled`. Увеличьте память или оптимизируйте приложение.