MAATRIX / Блог / Docker-контейнер не запускается

Docker-контейнер не запускается

Docker-контейнер не запускается

MAATRIX

Запускаете контейнер, а он тут же переходит в статус Exited или бесконечно перезапускается в Restarting. Docker-контейнер не запускается — и без логов непонятно, почему. На самом деле контейнер почти всегда честно сообщает причину падения, надо только правильно спросить. Ниже пошаговое решение проблемы: как прочитать причину сбоя по логам и exit code, разобрать типовые случаи — занятый порт, права, переменные окружения, битый образ — и запустить контейнер стабильно.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Первый шаг: читаем логи и статус

Не гадайте — спросите Docker напрямую. Почти любая причина падения видна в двух местах: в логах контейнера и в его статусе с кодом выхода. Начните с них:

# список контейнеров, включая упавшие, со статусом и кодом
docker ps -a
# логи конкретного контейнера — здесь обычно и лежит причина
docker logs имя_или_id
# последние строки и следим в реальном времени
docker logs --tail 50 -f имя_или_id

В 80% случаев ответ уже здесь: приложение внутри контейнера пишет в лог, на чём именно оно упало — не найден файл конфига, нет подключения к базе, синтаксическая ошибка, отказ в правах. Статус Exited (1) в docker ps -a подтверждает, что процесс завершился с ошибкой. Прочитайте лог до первой строки с ошибкой снизу вверх — там и корень. Только если лог пуст, переходим к разбору по exit code ниже.

Что говорит код выхода

Код выхода в скобках рядом со статусом Exited — это подсказка о характере падения. Несколько значений встречаются чаще всего, и по ним можно быстро сузить поиск. Exited (0) означает, что процесс завершился штатно, — для сервиса это обычно значит, что внутри контейнера главный процесс отработал и вышел (например, скрипт выполнился и закончился), а не «завис как демон».

Exited (1) — общая ошибка приложения, смотрите логи. Exited (125) — ошибка самого Docker (неверная команда запуска, проблема с образом). Exited (126) — файл найден, но не исполняемый (проблема прав или неверный ENTRYPOINT). Exited (127) — команда или файл не найдены внутри контейнера, частая причина — опечатка в пути или отсутствие бинарника в образе. Exited (137) — контейнер убит по нехватке памяти (OOM) или принудительной остановкой. Зная код, вы уже понимаете класс проблемы, не читая гору логов.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Заказать VPS под Docker

Занятый порт и конфликты

Одна из самых частых причин, по которой контейнер не поднимается, — порт уже занят. Docker не может пробросить порт на хост, если его держит другой процесс или другой контейнер. В логах это выглядит как port is already allocated или address already in use. Проверяем, кто сидит на порту:

# кто занял порт на хосте
ss -tulpn | grep :8080
# какие контейнеры и на каких портах работают
docker ps --format 'table {{.Names}}\t{{.Ports}}'

Решений два: либо освободить порт, остановив занявший его процесс, либо запустить контейнер на другом порту, поменяв левую часть в пробросе -p 8081:80. Помните, что в паре хост:контейнер конфликтует именно хостовый порт слева — контейнерный справа изолирован и совпадать может. Похожая история с именами: если контейнер с таким именем уже есть (пусть и упавший), Docker откажется создавать второй — удалите старый через docker rm.

Права, тома и переменные окружения

Вторая большая группа причин — окружение. Контейнеру не хватает данных или прав для старта. Частый случай — примонтированный том с неверными правами: процесс внутри контейнера работает не под root и не может писать в каталог, принадлежащий root на хосте. В логах — permission denied. Лечится приведением владельца тома к нужному UID или запуском с правильным пользователем.

# зайти внутрь упавшего образа в интерактивном режиме и проверить руками
docker run -it --rm образ sh
# посмотреть, какие переменные окружения реально видит контейнер
docker inspect имя --format '{{json .Config.Env}}'

Не менее часто виноваты переменные окружения: приложение ждёт DATABASE_URL или пароль, а его не передали — и оно падает при старте. Проверьте, что все нужные переменные заданы в docker run -e или в environment файла compose. Отдельная ловушка — том перекрывает содержимое образа: если смонтировать пустой каталог хоста поверх каталога с файлами внутри образа, файлы «исчезнут», и приложение не найдёт того, что ожидало.

Проблемы с самим образом

Иногда дело не в запуске, а в образе. Он мог не собраться до конца, скачаться повреждённым или быть собран под другую архитектуру. Последнее особенно актуально: образ, собранный под ARM, не запустится на x86-сервере, и наоборот — в логах будет exec format error. Проверьте архитектуру образа и сервера:

# архитектура образа
docker inspect образ --format '{{.Architecture}}'
# архитектура хоста
uname -m
# пересобрать образ начисто, без кэша
docker build --no-cache -t myapp .

Если образ битый или собрался с ошибкой, помогает чистая пересборка с --no-cache — Docker иногда цепляется за испорченный слой из кэша. Для скачанных образов сделайте docker pull заново. И проверьте, что тег указывает на то, что вы думаете: latest мог обновиться и притащить несовместимую версию. Явно фиксируйте версию тега, чтобы запуск был воспроизводимым.

Контейнер падает по нехватке памяти

Код выхода 137 и статус, в котором контейнер циклически перезапускается, часто означают, что его убивает OOM-killer — системе не хватает памяти. Это особенно заметно на VPS со скромным объёмом RAM, где тяжёлое приложение (база, JVM, сборка фронтенда) не влезает в лимит. Проверьте, так ли это:

# был ли контейнер убит по OOM
docker inspect имя --format '{{.State.OOMKilled}}'
# сколько памяти реально свободно на хосте
free -h

Если OOMKilled равно true, вариантов два: уменьшить аппетит приложения (лимиты JVM, число воркеров, размер кэша) или дать серверу больше памяти. На перегруженном по RAM сервере контейнеры будут падать снова и снова, и никакая настройка Docker это не обойдёт — нужен либо swap как временная мера, либо тариф с достаточной памятью под вашу нагрузку.

Профилактика: стабильный запуск контейнеров

Чтобы контейнеры поднимались предсказуемо, заведите несколько привычек. Фиксируйте версии образов явными тегами вместо latest. Прописывайте healthcheck, чтобы Docker сам видел, здоров ли сервис, а не только «процесс жив». Задавайте разумную политику рестарта (restart: unless-stopped), но следите за контейнерами в Restarting — бесконечный перезапуск маскирует реальную ошибку.

  • Всегда начинайте диагностику с docker logs и docker ps -a.
  • Не монтируйте пустые тома поверх нужных данных образа.
  • Передавайте все обязательные переменные окружения.
  • Следите за памятью — код 137 значит OOM.
  • Держите достаточно ресурсов под нагрузку контейнеров.

Стабильная работа Docker начинается с сервера, где хватает памяти и диска под ваши образы и данные. У MAATRIX VPS и выделенные серверы под Docker доступны в локациях RU, US и UK, с быстрым NVMe и оплатой из России картой или криптой. Когда ресурсов достаточно, а root-доступ полный, контейнеры перестают падать от нехватки памяти и места, и остаётся лишь чистая логика приложения.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.

Заказать VPS под Docker

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

С чего начать, если контейнер не запускается?

С docker logs имя и docker ps -a. Логи почти всегда содержат точную причину падения, а статус с кодом выхода уточняет класс проблемы. Читать лог удобнее снизу вверх до первой ошибки.

Что значит Exited (137)?

Контейнер убит по нехватке памяти (OOM) или принудительно остановлен. Проверьте docker inspect имя --format '{{.State.OOMKilled}}' и free -h. Решение — уменьшить потребление приложения или добавить памяти серверу.

Контейнер пишет port is already allocated — что делать?

Хостовый порт уже занят другим процессом или контейнером. Найдите его через ss -tulpn | grep :порт, освободите или запустите контейнер на другом порту, поменяв левую часть проброса -p.

Почему exec format error?

Образ собран под другую архитектуру процессора: например, ARM-образ на x86-сервере. Сверьте docker inspect образ --format '{{.Architecture}}' и uname -m, пересоберите или скачайте образ под нужную архитектуру.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.