Перейти к содержимому
EVI Solutions

Docker контейнер сразу завершается: как найти причину и исправить

Средне 15 мин Обновлено:

Краткий ответ

Когда 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. 1

    Проверьте статус и код выхода

    Выполните docker ps -a, чтобы увидеть все контейнеры, включая остановленные. Обратите внимание на столбец STATUS и код выхода. Код 0 означает, что процесс завершился нормально, 1 - общая ошибка, 127 - несуществующая команда, а 137 указывает на принудительную остановку, часто из-за памяти.

  2. 2

    Просмотрите логи

    Выполните docker logs <имя_или_id>. Если контейнер остановлен, добавьте --tail 100, чтобы увидеть последние сто строк. Логи чаще всего содержат точную причину, например, ошибку в конфигурации или сообщение, что команда не найдена.

  3. 3

    Запустите контейнер интерактивно

    Обойдите команду запуска и войдите в оболочку: docker run -it --entrypoint /bin/sh <образ>. Если в образе нет sh, попробуйте bash. Внутри контейнера вручную запустите приложение и увидите ошибку, которую обычно не видно.

  4. 4

    Проверьте команду и entrypoint

    Посмотрите Dockerfile и команду docker run. Убедитесь, что CMD или ENTRYPOINT в правильном формате и что путь к исполняемому файлу существует. Если используете docker compose, проверьте поле command в docker-compose.yml.

  5. 5

    Убедитесь, что основной процесс остаётся на переднем плане

    Приложение не должно запускаться в фоне или сразу завершаться. Если это скрипт, добавьте в конец цикл или запустите сервер, который слушает. Для контейнеров, которые должны просто оставаться активными, используйте tail -f /dev/null как временное решение.

  6. 6

    Проверьте переменные окружения и конфигурацию

    Сравните docker inspect <контейнер> с тем, что ожидает приложение. Отсутствующие переменные добавьте через -e или в секции environment. Проверьте также, что файлы конфигурации смонтированы по правильному пути.

  7. 7

    Проверьте разрешения и владельца

    Если приложение пишет в том или папку, убедитесь, что пользователь внутри контейнера имеет разрешение. В docker run добавьте --user или настройте Dockerfile. Ошибки с разрешениями часто видны в логах как Permission denied.

  8. 8

    Отключите healthcheck и зависимости

    Если используете Compose, временно закомментируйте healthcheck и depends_on, чтобы увидеть, работает ли контейнер самостоятельно. Затем возвращайте их по одному и наблюдайте за поведением.

  9. 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`. Увеличьте память или оптимизируйте приложение.

Поделиться
Не нашли решение?ИИ-помощник работает 24/7. Опишите проблему или отправьте скриншот ошибки и получите инструкцию для вашего случая.Спросить ИИ-помощника