Учавствовал ли в обнаружении причин перезагрузки контейнера в Docker
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Диагностика перезагрузок контейнеров в Docker
Да, неоднократно сталкивался с этой проблемой в production и разработке. Это одна из самых частых проблем при работе с Docker, и я выработал систематический подход к поиску причин.
Типичные причины перезагрузки
1. Out of Memory (OOM)
Одна из самых частых причин:
# Просмотр логов контейнера
docker logs my_container
# Ищём: "Killed", "OOMKilled", "exit code 137"
# Статус контейнера
docker inspect my_container | grep -i "oomkilled"
# Мониторинг памяти
docker stats my_container
В Docker Compose:
version: 3
services:
app:
image: myapp:latest
mem_limit: 512m # Лимит памяти
memswap_limit: 512m
environment:
- JVM_MEMORY=256m # Java heap
2. Application Crash
Приложение падает с ошибкой:
# Логи приложения
docker logs -f my_container
# Поиск исключений
docker logs my_container | grep -i exception
docker logs my_container | grep -i error
Например, в Java приложении:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Exception in thread "main" java.lang.StackOverflowError
Exception in thread "main" java.net.BindException: Address already in use
3. Health Check Failure
Kubernetes или Docker Compose перезагружают контейнер из-за failed health check:
version: 3
services:
app:
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# После 3 неудачных попыток контейнер перезагружается
4. Insufficient Resources на хосте
Хост не может выделить ресурсы:
# Проверка доступных ресурсов
docker info
# На Linux
free -h # Память
df -h # Диск
top # CPU
5. Неправильный ENTRYPOINT/CMD
Процесс завершается сразу после запуска:
# Неправильно - завершится мгновенно
FROM java:8
CMD java -jar app.jar
# Если jar не существует, контейнер упадёт
# Правильно с обработкой ошибок
FROM java:8
COPY app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
HEALTHCHECK --interval=30s --timeout=10s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
6. Port Binding Conflict
# Проверяем занятые порты
netstat -tlnp | grep :8080
lsof -i :8080
# Убиваем процесс на порту
kill -9 <PID>
Систематический подход к диагностике
Шаг 1: Базовая информация
# Статус контейнера
docker ps -a | grep my_container
# Детальная информация
docker inspect my_container
# Ищём в выводе:
# - State.Status: "exited", "restarting"
# - State.ExitCode: код выхода
# - RestartCount: количество перезагрузок
Шаг 2: Логирование
# Логи последний час
docker logs --since 1h my_container
# Логи с временами
docker logs -t my_container
# Только ошибки
docker logs my_container 2>&1 | grep -i error
# Tail (как tail -f)
docker logs -f my_container
Шаг 3: Коды выхода
Этот код много о чём говорит:
- 0: Нормальное завершение
- 1: Общая ошибка
- 125: Ошибка Docker
- 126: Команда не может быть выполнена
- 127: Команда не найдена
- 137: Убит сигналом KILL (OOMKilled)
- 143: Убит сигналом TERM
Шаг 4: Мониторинг ресурсов
# Real-time статистика
docker stats my_container
# История
docker stats --no-stream my_container
Шаг 5: Проверка конфигурации
# Dockerfile
docker history my_image
# Переменные окружения
docker inspect -f {{.Config.Env}} my_container
# Volumes
docker inspect -f {{.Mounts}} my_container
Реальный пример из практики
Проблема: Java приложение постоянно перезагружается в Docker
# 1. Проверяем логи
$ docker logs app
java.lang.OutOfMemoryError: Java heap space
# 2. Проверяем текущие лимиты
$ docker inspect app | grep -A 5 Memory
"Memory": 0, # No limit!
"MemorySwap": 0,
# 3. Проверяем как запущен контейнер
$ docker ps --no-trunc | grep app
# 4. Смотрим Dockerfile
$ cat Dockerfile
ENV JAVA_OPTS="-Xmx1g"
# Но в image всего 512m памяти выделено
# 5. Решение: добавляем лимит памяти
$ docker run -m 2g myapp:latest
Best Practices для предотвращения
# Dockerfile с правильной конфигурацией
FROM openjdk:11-jre-slim
COPY app.jar /app.jar
# Явно задаём JVM параметры
ENV JAVA_OPTS="-Xmx512m -Xms256m -XX:+UseG1GC"
# Health check
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
EXPOSE 8080
ENTRYPOINT ["java", "$JAVA_OPTS", "-jar", "/app.jar"]
Docker Compose с мониторингом:
version: 3.8
services:
app:
image: myapp:latest
mem_limit: 1g
memswap_limit: 1g
cpus: 1.0
restart: on-failure:5 # Перезагружаем max 5 раз
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Инструменты для мониторинга
- docker stats: встроенный монитор
- cAdvisor: Google контейнер адвайзер
- Prometheus + Grafana: метрики и графики
- ELK Stack: логирование
- Datadog, New Relic: commercial solutions
Итог
- Начни с
docker logsи кодов выхода - Проверь доступные ресурсы (
docker stats) - Убедись, что health check работает
- Установи правильные лимиты памяти и CPU
- Мониторь логи и метрики в production