Docker: контейнер сразу падает — причины и решение
Запускаете контейнер, а он тут же останавливается: Docker контейнер сразу падает и висит в статусе Exited. Это одна из самых частых проблем с Docker, и она почти всегда быстро диагностируется: контейнер честно пишет в логи, почему завершился, а его код выхода сужает круг причин. Не перезапускайте вслепую — сначала посмотрите логи и exit code. Разберём, как найти причину и поднять контейнер.
Содержание
- Первое действие: прочитайте логи и код выхода
- Причина 1: ошибка в приложении или конфиге (Exited 1)
- Причина 2: нехватка памяти (Exited 137)
- Причина 3: неверный CMD или ENTRYPOINT
- Причина 4: контейнер не рассчитан на постоянную работу
- Как отлаживать контейнер, который не поднимается
- Профилактика: чтобы контейнеры стартовали стабильно
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Первое действие: прочитайте логи и код выхода
Контейнер завершается, когда завершается его главный процесс. Причина почти всегда в логах, а характер — в коде выхода. Сначала посмотрите оба:
docker ps -a
docker logs имя_контейнера
docker ps -a покажет статус вроде Exited (1) или Exited (137) — число в скобках это код выхода, и он информативен. docker logs выведет то, что процесс успел написать перед смертью, — там обычно прямая причина: ошибка конфигурации, не найден файл, не удалось подключиться к базе, синтаксическая ошибка. Это ваш главный источник правды. Код Exited (0) означает, что процесс штатно завершился (для разовых задач это норма), Exited (1) — ошибка приложения, Exited (137) — процесс убит, чаще всего из-за нехватки памяти. Прочитав логи и код, вы уже знаете, куда копать.
Причина 1: ошибка в приложении или конфиге (Exited 1)
Код Exited (1) и большинство ненулевых кодов означают, что приложение внутри контейнера упало с ошибкой. Логи почти всегда показывают, что именно: не найден конфигурационный файл, не задана обязательная переменная окружения, синтаксическая ошибка, приложение не смогло подключиться к зависимому сервису. Читайте вывод docker logs внимательно — там текст ошибки приложения, как если бы оно запускалось напрямую.
Частый случай — не передана нужная переменная окружения. Приложение стартует, не находит, например, строку подключения к базе, и падает. Проверьте, что все обязательные переменные заданы при запуске или в compose-файле:
docker run --env-file .env myimage
Другой типичный источник — контейнер зависит от базы или другого сервиса, который ещё не готов: приложение пытается подключиться при старте, не может и завершается. Тогда нужны корректный порядок запуска и повторные попытки подключения. В любом случае лечение идёт от текста ошибки в логах: устраните конкретную причину, на которую жалуется приложение, и контейнер поднимется.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под DockerПричина 2: нехватка памяти (Exited 137)
Код Exited (137) означает, что процесс был убит сигналом KILL — почти всегда из-за нехватки памяти (OOM, out of memory). Либо контейнеру задан лимит памяти, который приложение превысило, либо на сервере в принципе кончилась RAM, и система убила процесс. Проверьте, не в OOM ли дело, и сколько памяти на сервере:
docker inspect имя_контейнера | grep -i oomkilled
free -m
Если OOMKilled равно true — подтверждение диагноза. Решение зависит от причины: если задан слишком жёсткий лимит памяти контейнеру (--memory), поднимите его под реальные потребности приложения; если память кончилась на всём сервере — уменьшите потребление, разнесите сервисы или добавьте RAM. Тяжёлые приложения (базы, сборки, обработка данных) особенно склонны к OOM на скромных серверах. Код 137 — это почти всегда честный сигнал «памяти не хватило», и лечится он либо настройкой лимитов, либо увеличением ресурсов.
Причина 3: неверный CMD или ENTRYPOINT
Контейнер живёт, пока работает его главный процесс, заданный в CMD или ENTRYPOINT. Если команда неверна — опечатка, не тот путь, бинарник не найден, скрипт без прав на исполнение — контейнер немедленно завершается. В логах будет что-то вроде exec: "start.sh": not found или permission denied. Проверьте, что команда запуска корректна и файл существует внутри образа:
docker run -it --entrypoint sh myimage
Запуск с --entrypoint sh даёт интерактивную оболочку внутри контейнера, где можно вручную проверить наличие файлов, права и работоспособность команды старта. Частые ошибки — забыли chmod +x на entrypoint-скрипте, указали неверный путь к бинарнику, команда рассчитана на другую базовую систему (например, bash в образе, где только sh). Исправьте команду в Dockerfile или compose и пересоберите образ. Понимание, что контейнер — это один процесс, снимает многие вопросы: нет живого главного процесса — нет контейнера.
Причина 4: контейнер не рассчитан на постоянную работу
Иногда контейнер «падает», хотя всё правильно: он выполнил свою разовую задачу и штатно завершился с кодом 0. Так ведут себя образы для одноразовых команд (миграции, скрипты, утилиты) — они не сервисы и не должны висеть постоянно. Если вы ожидали долгоживущий сервис, а видите Exited (0), проверьте, действительно ли главный процесс должен работать непрерывно. Веб-сервер и демон работают в форграунде и держат контейнер, а вот команда, которая отработала и вышла, контейнер не удержит.
Частая ошибка — запустить сервис в фоне внутри контейнера (демонизировать его), после чего главный процесс сразу завершается, и контейнер умирает, хотя «сервис вроде запущен». Правильно — запускать процесс на переднем плане, не демонизируя: тогда он и есть главный процесс контейнера. Если вам действительно нужна разовая задача — это нормальное поведение, и статус Exited (0) не ошибка. Различайте эти сценарии, прежде чем чинить то, что работает как задумано.
Как отлаживать контейнер, который не поднимается
Когда логи не дают полной картины, отладьте контейнер интерактивно. Запустите его с оболочкой вместо основной команды и проверьте окружение изнутри:
docker run -it --entrypoint sh myimage
Внутри вы можете вручную запустить команду старта и увидеть реальную ошибку, проверить наличие файлов, переменных, прав, доступность зависимостей. Это мощный приём: вы оказываетесь в той же среде, что и падающий процесс, но контролируете её. Для уже упавшего контейнера полезны docker inspect (детали конфигурации, лимиты, код выхода) и просмотр событий docker events. Пошаговая отладка изнутри почти всегда выявляет причину, когда одних логов мало, — вы буквально воспроизводите падение руками и видите, на чём именно спотыкается запуск.
Профилактика: чтобы контейнеры стартовали стабильно
Чтобы контейнеры не падали на старте, соблюдайте несколько принципов. Запускайте главный процесс на переднем плане, не демонизируйте его внутри контейнера. Передавайте все обязательные переменные окружения и проверяйте их наличие в самом приложении с понятной ошибкой, если чего-то нет. Задавайте разумные лимиты памяти и следите за ресурсами сервера, чтобы избежать OOM. Описывайте зависимости и порядок запуска в compose, а приложение делайте устойчивым к временной недоступности базы через повторные попытки.
Используйте healthcheck, чтобы Docker знал реальное состояние сервиса, и политику перезапуска (restart: unless-stopped) для автоматического восстановления после сбоев — но помните, что перезапуск не лечит ошибку конфигурации, а лишь повторяет её. Держите Dockerfile и compose под контролем версий, чтобы любой сбой можно было воспроизвести и откатить. И начинайте диагностику всегда с docker logs и кода выхода: контейнер честно говорит, почему умер, и в большинстве случаев причина находится за минуту.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под DockerОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Как узнать, почему контейнер сразу падает?
Посмотрите docker ps -a (код выхода) и docker logs имя (сообщение процесса перед смертью). Код Exited (1) — ошибка приложения, Exited (137) — нехватка памяти, Exited (0) — штатное завершение.
Что означает Exited (137)?
Процесс убит из-за нехватки памяти (OOM). Проверьте docker inspect на OOMKilled: true и память сервера. Поднимите лимит контейнера или уменьшите потребление либо добавьте RAM.
Контейнер выходит с кодом 0 сразу после старта — это ошибка?
Не обязательно: значит, главный процесс штатно завершился. Так ведут себя разовые задачи. Для сервиса убедитесь, что процесс работает на переднем плане и не демонизирован.
Как оплатить сервер под Docker из России?
В MAATRIX — картой российского банка, через СБП, криптовалютой или токеном MAAT. Иностранная карта не нужна.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.