Методики отладки контейнеров

TL;DR: Контейнер падает? docker logsdocker inspectdocker exec. Нет shell? Подключи netshoot. Нужно внутрь образа? Используй dive.

Когда контейнер падает или ведет себя странно, нужно уметь быстро диагностировать проблему. В этом гайде собраны техники от базового просмотра логов до продвинутого сетевого анализа с использованием sidecar-контейнеров.

1. Анализ “мертвого” контейнера

Контейнер упал (Exited). Как понять почему?

Шаг 1: Логи

Смотрим STDOUT/STDERR.

docker logs <container_name>
# Если логов слишком много, смотрим последние 100 строк
docker logs --tail 100 <container_name>

Шаг 2: Inspect (Код выхода)

Если логов нет (приложение упало до инициализации логгера), смотрим код выхода.

docker inspect <container_name> --format='{{.State.ExitCode}}'
  • 137: OOM Killer (нехватка памяти).
  • 1: Ошибка приложения (смотрите код).
  • 0: Приложение решило, что работа закончена (возможно, неправильный CMD).

Шаг 3: Переопределение Entrypoint

Если контейнер падает мгновенно (CrashLoopBackOff), вы не успеваете зайти внутрь. Запустите его с командой sleep, чтобы он “повис” и дал вам время осмотреться.

# Переопределяем команду запуска на бесконечный сон
docker run -d --name debug-app --entrypoint sleep my-broken-image infinity
 
# Заходим внутрь
docker exec -it debug-app sh
# Теперь пробуем запустить приложение вручную и смотрим ошибки
/app/start.sh

2. Отладка работающего контейнера

Подключение (Exec)

docker exec -it <container_name> sh
# Если sh нет (Alpine/Distroless), пробуйте:
# docker exec -it <container_name> /bin/bash

Просмотр процессов

Не используйте top внутри контейнера (его может не быть). Используйте docker:

docker top <container_name>

Проверка файлов (без входа)

Можно скопировать подозрительный конфиг наружу для анализа:

docker cp <container_name>:/etc/nginx/nginx.conf ./debug_nginx.conf

3. Сетевая отладка (Netshoot)

Частая проблема: “Приложение не видит базу данных”. В минимальных образах (Alpine, Distroless) нет утилит curl, ping, telnet, nslookup. Устанавливать их (apt-get install) долго и грязно.

Решение: Sidecar Container (Netshoot) Запустите швейцарский нож сетевой отладки (nicolaka/netshoot), подключив его к сети целевого контейнера.

# Подключаем netshoot к сети контейнера 'my-app'
docker run -it --rm --network container:my-app nicolaka/netshoot

Теперь вы находитесь “внутри” сетевого стека my-app. Вы видите его IP, его порты и localhost.

  • ping google.com — есть ли интернет?
  • nslookup db — работает ли DNS?
  • nc -zv db 5432 — открыт ли порт базы?
  • tcpdump -i eth0 — сниффинг трафика.

4. Отладка образов (Dive)

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

docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive <image_name>

Она покажет дерево файлов и позволит найти “мусор” (например, забытый кэш apt или исходники в финальном слое).

5. Восстановление данных (Rescue Volume)

Если контейнер с БД умер и не поднимается, нужно спасти данные из Volume.

# Монтируем volume к временному контейнеру busybox
docker run --rm -v my-db-data:/data -v $(pwd):/backup busybox \
  tar cvf /backup/backup.tar /data

Теперь у вас есть архив backup.tar на хосте.

Типичные ошибки

ОшибкаСимптомРешение
docker exec в остановленный контейнерError: container is not runningЗапустить с docker run --entrypoint sleep ... infinity, потом exec
Distroless — нет bash/shexec: "sh": not foundПодключить netshoot к namespace контейнера или использовать debug image
Не смотрят exit code«Контейнер просто упал»docker inspect --format='{{.State.ExitCode}}' — 137 = OOM, 1 = ошибка приложения
Логи обрезаныСтарые логи недоступныdocker logs --since 1h или настроить централизованное логирование