Docker контейнер упал с кодом 1: Полное руководство по диагностике и решению

Docker контейнер упал с кодом 1: Полное руководство по диагностике и решению

Вы запускаете Docker контейнер, а он мгновенно завершает работу с загадочным кодом 1. Ни логов, ни понятных ошибок — только разочарование и потраченное время. Эта ошибка — одна из самых частых и раздражающих в экосистеме Docker, но её решение лежит в чётком понимании того, что на самом деле означает этот код возврата и как систематически подойти к диагностике.

Что на самом деле означает код 1?

Когда контейнер Docker завершает работу с кодом 1, это не специфическая ошибка Docker. Это общий код выхода в Unix-подобных системах, означающий «Общая ошибка» или «Неудачное завершение». Контейнер — это всего лишь процесс, и код 1 говорит о том, что основной процесс внутри контейнера (то, что указано как CMD или ENTRYPOINT) завершился неудачно. Проблема всегда внутри.

Ключевой момент: Docker лишь сообщает о результате работы вашего приложения. Код 1 — это сигнал от самого приложения или скрипта внутри контейнера.

Систематическая диагностика: Пошаговый план

Не гадайте на кофейной гуще. Следуйте этому алгоритму, чтобы найти корень проблемы.

Шаг 1: Проверьте логи контейнера

Это первое и самое важное действие. Даже если контейнер упал, его логи часто остаются доступны короткое время.

docker logs <имя_или_id_контейнера>

Используйте флаг -f (follow) для отслеживания в реальном времени при перезапуске, или --tail 50 для просмотра последних строк. Часто ответ прячется именно здесь.

Шаг 2: Запустите контейнер в интерактивном режиме

Если логи не помогают, зайдите внутрь. Запустите контейнер с интерактивной оболочкой, переопределив точку входа.

docker run -it --entrypoint=/bin/sh <образ_контейнера>

Или для уже упавшего контейнера, если он ещё существует:

docker commit <контейнер> temp-image && docker run -it temp-image /bin/sh

Теперь вы можете вручную запустить команду из CMD и увидеть ошибку своими глазами.

Шаг 3: Проверьте команду ENTRYPOINT/CMD

Убедитесь, что команда, которую контейнер пытается выполнить, существует и исполняема внутри контейнера. Распространённые ошибки:

  • Отсутствует скрипт или бинарный файл, на который ссылается CMD.
  • Скрипт имеет ошибки синтаксиса (например, баш-скрипт без shebang #!/bin/sh).
  • У скрипта нет прав на выполнение. Исправьте в Dockerfile: RUN chmod +x /your/script.sh.

Совет: Всегда явно указывайте shell для скриптов в CMD, например CMD [\"sh\", \"-c\", \"/app/start.sh\"]. Это делает запуск более предсказуемым.

Шаг 4: Ищите ошибки зависимостей и среды

Приложение может требовать переменные окружения, файлы конфигурации или порты.

  1. Переменные окружения: Проверьте, все ли необходимые переменные (ENV в Dockerfile или переданные через -e) установлены и имеют корректные значения. Используйте docker inspect для проверки.
  2. Файлы и volumes: Убедитесь, что необходимые файлы присутствуют по ожидаемым путям. Контейнер — изолированная среда.
  3. Порты: Конфликт портов (когда порт уже занят на хосте) обычно приводит к другой ошибке, но проверить стоит.

Шаг 5: Анализ Dockerfile

Постройте образ с более подробным выводом и проверьте каждый слой.

docker build --no-cache --progress=plain -t test-image .

Ищите ошибки в командах RUN. Часто проблема — в некорректной установке пакетов, отсутствующих зависимостях или неправильных путях.

Типичные причины и их решения

  • Ошибка в скрипте запуска: Добавьте set -e в начало bash-скриптов, чтобы они завершались при первой ошибке, и используйте set -x для отладки вывода.
  • Отсутствие файла: Добавьте проверку существования критических файлов в скрипте запуска.
  • Проблемы с правами: Убедитесь, что пользователь в контейнере (если используется USER) имеет права на запись в необходимые директории.
  • Исчерпание памяти (OOM Killer): Проверьте логи хоста (dmesg | grep -i kill). Увеличьте лимиты памяти для контейнера через -m.

Продвинутые методы отладки

Если стандартные методы не помогают:

  1. Запустите контейнер с флагом --init, чтобы использовать минимальный init-процесс, который корректно обрабатывает сигналы.
  2. Используйте docker events в реальном времени для наблюдения за событиями жизненного цикла контейнера.
  3. Проверьте, не завершается ли процесс из-за сигнала (например, SIGSEGV). Добавьте в скрипт запуска обработку сигналов или используйте статически скомпилированный бинарник для теста.

FAQ: Часто задаваемые вопросы

Контейнер падает с кодом 1, но в логах ничего нет. Что делать?

Скорее всего, ошибка происходит до того, как приложение инициализирует логирование (например, при разборе аргументов командной строки или загрузке конфига). Используйте интерактивный запуск с shell и выполняйте команду CMD вручную.

Как предотвратить автоматическое удаление упавшего контейнера?

Не используйте флаг --rm при отладке. Или запускайте с docker run --restart=no .... Упавший контейнер можно исследовать командой docker inspect <контейнер>.

Может ли проблема быть в базовом образе?

Да, особенно если вы используете теги типа :latest. Попробуйте зафиксировать конкретную версию образа (например, node:18-alpine вместо node:latest) и пересобрать.

Код 1 появляется только в production, а локально всё работает.

Классическая проблема различия сред. Сравните:

  • Версии Docker (docker version)
  • Архитектуру (linux/amd64 vs arm64)
  • Переменные окружения
  • Смонтированные volumes и их содержимое
  • Доступные ресурсы (память, CPU)
Используйте docker-compose или аналоги для унификации среды.