Вы запускаете 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: Ищите ошибки зависимостей и среды
Приложение может требовать переменные окружения, файлы конфигурации или порты.
- Переменные окружения: Проверьте, все ли необходимые переменные (
ENVв Dockerfile или переданные через-e) установлены и имеют корректные значения. Используйтеdocker inspectдля проверки. - Файлы и volumes: Убедитесь, что необходимые файлы присутствуют по ожидаемым путям. Контейнер — изолированная среда.
- Порты: Конфликт портов (когда порт уже занят на хосте) обычно приводит к другой ошибке, но проверить стоит.
Шаг 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.
Продвинутые методы отладки
Если стандартные методы не помогают:
- Запустите контейнер с флагом
--init, чтобы использовать минимальный init-процесс, который корректно обрабатывает сигналы. - Используйте
docker eventsв реальном времени для наблюдения за событиями жизненного цикла контейнера. - Проверьте, не завершается ли процесс из-за сигнала (например, 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)