← Назад к вопросам

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

1.8 Middle🔥 181 комментариев
#Docker и контейнеризация

Условие

Вам дали скомпилированный бинарник приложения без исходников. При запуске в Docker контейнере приложение не работает.

Задача

Опишите пошаговый процесс отладки:

  1. Как проверить, что контейнер запустился?
  2. Как посмотреть логи контейнера?
  3. Как войти внутрь контейнера для отладки?
  4. Какие инструменты использовать для диагностики?
  5. Как проверить сетевые соединения изнутри контейнера?

Сценарии проблем

  • Приложение падает сразу после старта
  • Приложение работает, но недоступно по сети
  • Приложение медленно отвечает
  • Приложение потребляет много памяти

Команды для каждого сценария

Приведите конкретные команды docker и linux для диагностики каждой проблемы.

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Решение

1. Проверка статуса контейнера

Основные команды

# Список всех контейнеров
docker ps -a

# Формат с дополнительной информацией
docker ps -a --format 'table {{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Ports}}'

# Только ID
docker ps -aq

# С временем создания
docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.CreatedAt}}\t{{.Status}}"

Интерпретация статусов

# GOOD: Контейнер работает
Up 2 hours                  # ✅ Нормально работает
Up 2 hours (healthy)        # ✅ Healthcheck OK
Up 2 hours (unhealthy)      # ⚠️ Healthcheck FAILED

# BAD: Контейнер не работает
Exited (0)                  # ✅ Завершился корректно (код 0)
Exited (1)                  # ❌ Ошибка (код 1)
Exited (137)                # ❌ Убит сигналом (OOMKilled)
Exited (139)                # ❌ Segmentation fault
Created                     # ❌ Создан но не запущен
Restarting                  # ❌ Постоянно перезапускается
Dead                        # ❌ Процесс зависший

Детальная информация о контейнере

# Полная информация
docker inspect <container_id>

# Только состояние
docker inspect <container_id> --format='{{.State}}'

# Exit code
docker inspect <container_id> --format='{{.State.ExitCode}}'

# Started time и finished time
docker inspect <container_id> --format='Started: {{.State.StartedAt}} Finished: {{.State.FinishedAt}}'

# IP адрес контейнера
docker inspect <container_id> --format='{{.NetworkSettings.IPAddress}}'

2. Просмотр логов контейнера

Основные команды

# Все логи
docker logs <container_id>

# Последние 100 строк
docker logs --tail 100 <container_id>

# В реальном времени (follow)
docker logs -f <container_id>

# С временными метками
docker logs -t <container_id>

# Последние 10 минут
docker logs --since 10m <container_id>

# С форматированием времени
docker logs --timestamps <container_id> 2>&1 | head -50

Анализ логов

# Поиск ошибок
docker logs <container_id> 2>&1 | grep -i error

# Последняя ошибка
docker logs <container_id> 2>&1 | tail -20

# Количество логов
docker logs <container_id> 2>&1 | wc -l

# Сохранение в файл для анализа
docker logs <container_id> > container.log 2>&1

# Поиск pattern
docker logs <container_id> 2>&1 | grep "Connection refused"

# Уникальные ошибки
docker logs <container_id> 2>&1 | grep -i error | sort | uniq

Логирование из Dockerfile

# Если приложение не логирует в stdout
# Перенаправьте логи
# В Dockerfile:
# CMD ["./app", "--log-file=-"]  # - = stdout
# Или
# CMD ["/bin/sh", "-c", "./app 2>&1"]  # Перенаправляем stderr в stdout

3. Вход внутрь контейнера для отладки

Запущенный контейнер

# Interactive shell
docker exec -it <container_id> /bin/bash
# или
docker exec -it <container_id> /bin/sh

# Выполнить одну команду
docker exec <container_id> ps aux

# С переменной окружения
docker exec -e DEBUG=1 <container_id> /bin/bash

# От другого пользователя
docker exec -u root <container_id> /bin/bash

Остановленный контейнер

# Запустить новый контейнер с тем же image
docker run -it <image_name> /bin/bash

# Или создать контейнер на основе остановленного
docker commit <container_id> debug-image
docker run -it debug-image /bin/bash

# Запустить контейнер на основе образа и замаунтить volume
docker run -it -v /path/on/host:/data <image_name> /bin/bash

Отладка с помощью Dockerfile

# Добавьте debug tools в образ
FROM ubuntu:22.04

# Установка debug tools
RUN apt-get update && apt-get install -y \
    curl \
    wget \
    netcat \
    telnet \
    strace \
    ltrace \
    tcpdump \
    procps \
    vim \
    htop

COPY ./app /app
WORKDIR /app

CMD ["./app"]

4. Диагностические инструменты внутри контейнера

Минимальный набор

# Внутри контейнера проверяем
ls -la           # Файловая система
pwd              # Рабочая директория
env              # Переменные окружения
ps aux           # Процессы
df -h            # Место на диске
free -h          # Память
netstat -tlnp    # Открытые порты
ifconfig         # Сеть

Встроенные инструменты для мониторинга

# Основные команды в контейнере

# Вывести переменные окружения, которые может использовать приложение
env | sort

# Проверить рабочую директорию
pwd && ls -la

# Проверить бинарник
file /app/myapp
ldd /app/myapp      # Зависимости (если бинарник скомпилирован для Linux)

# Запустить с debug информацией
strace -e trace=file ./myapp     # Отследить файловые операции
strace -e trace=network ./myapp  # Отследить сетевые операции

# Посмотреть какие системные вызовы делает приложение
ltrace ./myapp  # Library calls

# Проверить правильность ELF образа
readelf -l /app/myapp

Работа с сетью

# Проверить на что слушает приложение
netstat -tlnp
netstat -tlnp | grep LISTEN

# Или
ss -tlnp

# Проверить открытые соединения
netstat -anp
netstat -anp | grep ESTABLISHED

# DNS
nslookup google.com
cat /etc/resolv.conf    # DNS серверы

# Проверка порта в локальной сети
netcat -v <host> <port>
netcat -zv <host> <port>    # -z = только проверка, без отправки

# TCP/UDP
nc -u <host> <port>  # UDP

# Curl для HTTP
curl -v http://localhost:8080
curl -v http://localhost:8080/health

5. Проверка сетевых соединений

Из host машины

# Проверить что контейнер слушает
docker port <container_id>

# Прямое подключение к контейнеру
IP=$(docker inspect <container_id> --format='{{.NetworkSettings.IPAddress}}')
netcat -v $IP 8080

# curl с verbose
curl -v http://$IP:8080

# tcpdump - перехват пакетов
sudo tcpdump -i docker0 'port 8080'

Внутри контейнера

# Проверить что слушает
netstat -tlnp
ss -tlnp

# Если порт занят другим процессом
fuser 8080/tcp          # Какой процесс слушает
lsof -i :8080           # Список файлов для порта

# Проверить localhost
netcat -v localhost 8080
curl -v http://localhost:8080

# Проверить 0.0.0.0 (все интерфейсы)
netcat -v 0.0.0.0 8080

# Проверить сетевой интерфейс
ifconfig
ip addr

# DNS resolution
nslookup <external_service>
host <external_service>

6. Сценарий 1: Приложение падает сразу

Диагностика

# Шаг 1: Проверить статус
docker ps -a
# Status: Exited (1) или Exited (127)

# Шаг 2: Посмотреть логи
docker logs <container_id>
# Обычно видна ошибка в логах

# Шаг 3: Проверить exit code
docker inspect <container_id> --format='{{.State.ExitCode}}'
# 0 = успех
# 1 = ошибка приложения
# 127 = бинарник не найден
# 128+signal = убит сигналом
# 137 = OOMKilled

# Шаг 4: Если логов мало - запустить вручную
docker run --rm <image_name> ./app
# Или с bash для отладки
docker run --rm -it <image_name> /bin/bash
# Внутри: ./app

Возможные причины

# 1. Бинарник не совместим с ОС в образе
docker run --rm <image_name> file /app/myapp
# Проверить что это Linux executable

# 2. Отсутствуют зависимости
docker run --rm <image_name> ldd /app/myapp
# Если libc не найдена - нужна glibc base image

# 3. Отсутствуют переменные окружения
docker run --rm -e CONFIG_PATH=/etc/config <image_name> ./app

# 4. Отсутствуют файлы конфигурации
docker run --rm -v /local/config:/app/config <image_name> ./app

# 5. Неправильные права доступа
docker run --rm <image_name> ls -la /app/myapp
# Должно быть executable (-x)

7. Сценарий 2: Приложение работает, но недоступно по сети

Диагностика

# Шаг 1: Проверить что контейнер работает
docker ps | grep <container_id>
# Status: Up

# Шаг 2: Проверить логи нет ли ошибок
docker logs <container_id>

# Шаг 3: Войти в контейнер
docker exec -it <container_id> /bin/bash

# Шаг 4: Проверить что приложение слушает внутри контейнера
netstat -tlnp
ss -tlnp

# Шаг 5: Проверить адрес и порт
# ВАЖНО: Должно быть 0.0.0.0:8080 или :::8080 (IPv6)
# НЕ должно быть 127.0.0.1:8080 (только localhost)

# Шаг 6: Проверить с curl внутри контейнера
curl -v http://localhost:8080

Возможные причины

# 1. Приложение слушает на localhost только
# Решение: Измените конфигурацию на 0.0.0.0
# ./app --bind 0.0.0.0:8080

# 2. Неправильное port mapping
docker port <container_id>     # Проверить mapping

# Если пусто, перезапустите с портом
docker stop <container_id>
docker rm <container_id>
docker run -p 8080:8080 <image_name>

# 3. Firewall блокирует порт
sudo iptables -L -n | grep 8080
sudo ufw status | grep 8080

# 4. Неправильный порт в EXPOSE
docker inspect <image_name> | grep -i expose

8. Сценарий 3: Приложение медленно отвечает

Диагностика

# Шаг 1: Проверить CPU и память
docker stats <container_id>

# Шаг 2: Если CPU 100% - горячий цикл
# Войти в контейнер
docker exec -it <container_id> /bin/bash

# Посмотреть процессы
top
ps aux

# Отследить системные вызовы
strace -p <pid> -e trace=open,read,write

# Шаг 3: Если память растет - утечка
# Мониторить память
watch 'docker stats <container_id>'

# Шаг 4: Проверить I/O
docker exec <container_id> iostat
docker exec <container_id> vmstat

# Шаг 5: Если медленнее всего конкретный endpoint
# Проверить логи с временами
docker logs -t <container_id> | tail -100

Оптимизация

# Увеличить ресурсы контейнера
docker run --cpus="2" --memory="4g" <image_name>

# Профилирование с помощью perf (если есть)
docker exec --privileged <container_id> perf record -F 99 -p <pid>

9. Сценарий 4: Приложение потребляет много памяти

Диагностика

# Шаг 1: Текущее использование
docker stats --no-stream <container_id>

# Шаг 2: История
docker stats <container_id> --no-stream
# Запустить несколько раз

# Шаг 3: Войти в контейнер
docker exec -it <container_id> /bin/bash

# Шаг 4: Посмотреть как распределена память
cat /proc/meminfo
free -h

# Шаг 5: По процессам
ps aux --sort=-%mem | head

# Шаг 6: Отследить утечку памяти
# Если память постоянно растет
watch -n 1 'free -h'
watch -n 1 'ps aux --sort=-%mem | head -10'

# Шаг 7: Профилирование памяти
# Если приложение на Python
python -m memory_profiler ./app

# На Go
pprof http://localhost:6060/debug/pprof/heap

Решение

# Увеличить лимит памяти
docker run --memory="8g" <image_name>

# Проверить что есть swap
free -h

# Если утечка памяти в приложении - отладить код
# Если нет - может быть проблема с зависимостями (library leak)

# Перезагружать контейнер периодически
# В docker-compose
restart_policy:
  condition: on-failure
  max_retries: 5

10. Комплексная проверка контейнера

#!/bin/bash
# Скрипт для полной диагностики контейнера

CONTAINER=$1

echo "=== Статус контейнера ==="
docker ps -a | grep $CONTAINER

echo ""
echo "=== Логи (последние 50 строк) ==="
docker logs --tail 50 $CONTAINER

echo ""
echo "=== Exit code ==="
docker inspect $CONTAINER --format='{{.State.ExitCode}}'

echo ""
echo "=== IP адрес ==="
docker inspect $CONTAINER --format='{{.NetworkSettings.IPAddress}}'

echo ""
echo "=== Port mapping ==="
docker port $CONTAINER

echo ""
echo "=== Ресурсы ==="
docker stats --no-stream $CONTAINER

echo ""
echo "=== Открытые порты внутри ==="
docker exec $CONTAINER netstat -tlnp 2>/dev/null || docker exec $CONTAINER ss -tlnp

echo ""
echo "=== Переменные окружения ==="
docker exec $CONTAINER env

echo ""
echo "=== Файловая система ==="
docker exec $CONTAINER ls -la /

11. Best practices для отладки

# 1. Используйте healthcheck в Dockerfile
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1

# 2. Логируйте в stdout/stderr
CMD ["./app", "--log-file=/dev/stdout"]

# 3. Используйте minimal images (alpine)
FROM alpine:latest

# 4. Добавьте debug tools в dev image
FROM python:3.11 as debug
RUN apt-get update && apt-get install -y curl netcat

# 5. Используйте docker-compose для локального тестирования
docker-compose up

# 6. Сохраняйте логи для анализа
docker logs <container> > /tmp/container.log

# 7. Используйте docker events для мониторинга
docker events --filter "container=<container_id>"

# 8. Commitьте debug образы для сохранения состояния
docker commit <container_id> debug-image:latest
docker run -it debug-image:latest /bin/bash
Отладка неработающего Docker контейнера | PrepBro