Как дебажить в Docker контейнере
DevOpsDockerдебагинфраструктураконтейнеры
Что проверяют
Умеете ли вы найти причину, когда приложение работает локально и ломается в контейнере. Интервьюер ждёт не список команд, а порядок действий. Следом часто спрашивают, как подключить отладчик IDE к процессу внутри контейнера.
Как отвечать
Идите от дешёвого к дорогому:
- логи и статус:
docker logs -f --tail 200 <имя>иdocker ps -a. Код выхода 137 означает SIGKILL, часто от нехватки памяти, это видно вdocker inspectпо полюState.OOMKilled. Чтобы вывод Python не застревал в буфере, в образе задаютPYTHONUNBUFFERED=1; - окружение:
docker inspectпокажет переменные, монтирования и сеть,docker exec <имя> envпокажет то, что видит процесс; - шелл внутри:
docker exec -it <имя> sh. В alpine есть толькоsh, в distroless шелла нет вовсе, и тогда выручаетdocker debugиз Docker Desktop или соседний контейнер с утилитами через--network container:<имя>; - падение на старте:
docker compose run --rm --entrypoint sh app, и команда запуска выполняется руками; - пошаговая отладка:
pdbвходит в стандартную библиотеку, ставить его не нужно. Дляbreakpoint()контейнеру нужен терминал:stdin_open: trueиtty: trueв compose, затемdocker attach. Удобнееdebugpy:python -m debugpy --listen 0.0.0.0:5678 --wait-for-client -m app, порт 5678 пробрасывается наружу, а VS Code подключается attach-конфигурацией с маппингом путей; - зависание:
py-spy dump --pid 1внутри контейнера покажет стеки всех потоков, для этого нужен--cap-add SYS_PTRACE.
Где спотыкаются
Слушают отладчиком 127.0.0.1. Внутри контейнера это его собственный loopback, и с хоста подключиться не получится, нужен 0.0.0.0.
Ставят отладочные пакеты в боевой образ. debugpy и компиляторы держат в отдельной dev-стадии многоэтапной сборки.
Правят файлы прямо в контейнере через exec. После пересоздания правки исчезают, а баг в образе остаётся, поэтому фикс вносят в код или Dockerfile и пересобирают.