Контейнер падает сразу после старта

Порядок разбора, который закрывает большинство случаев.

Сначала — логи и код возврата

docker ps -a                  # статус и Exit Code
docker logs <container>       # что успело написаться
docker inspect <container> --format '{{.State.ExitCode}} {{.State.Error}}'

Код возврата сразу сужает поиск:

Код Что обычно значит
0 процесс завершился штатно — скорее всего, ему нечего было делать
1 ошибка приложения, смотрите логи
125 ошибка самого Docker (неверные аргументы)
126 файл найден, но не исполняемый
127 команда не найдена
137 SIGKILL — почти всегда OOM
143 SIGTERM — остановлен штатно

Exit code 0: главный процесс завершился

Контейнер живёт ровно столько, сколько живёт его главный процесс. Если запустить сервис в фоне, контейнер немедленно остановится:

CMD ["nginx"]         # уходит в фон → контейнер завершается
CMD ["nginx", "-g", "daemon off;"]   # остаётся на переднем плане

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

Exit code 137: не хватило памяти

docker inspect <container> --format '{{.State.OOMKilled}}'

true — контейнер вышел за лимит памяти и был убит ядром. Либо поднимите лимит, либо ограничьте потребление приложения. Для JVM и Node важно, чтобы heap был меньше лимита контейнера, иначе процесс убивают до того, как сработает сборщик мусора.

Exit code 127: команда не найдена

Обычно это разница между базовыми образами. Alpine использует musl, а не glibc: бинарник, собранный под Debian, там не запустится, хотя файл на месте. Сообщение при этом выглядит так, будто файла нет.

docker run --rm -it --entrypoint sh myimage
ls -l /app/binary
ldd /app/binary       # каких библиотек не хватает

Когда логи пусты

Переопределите точку входа и посмотрите изнутри:

docker run --rm -it --entrypoint sh myimage

Дальше запускайте команду руками — ошибка станет видна. Если контейнер уже упал и нужно его состояние:

docker commit <container> debug-image
docker run --rm -it --entrypoint sh debug-image

Проверьте очевидное

Больше половины случаев — это отсутствующая переменная окружения или несмонтированный файл конфигурации:

docker inspect <container> --format '{{json .Config.Env}}' | tr ',' '\n'
docker inspect <container> --format '{{json .Mounts}}'