Без healthcheck Docker считает контейнер «живым», если PID 1 работает. Но сервис может повиснуть: deadlock, утечка памяти, потеря соединения с БД — процесс жив, но не обслуживает запросы.
# Dockerfile с HEALTHCHECK
FROM golang:1.22-alpine AS builder
# ... build stages ...
FROM alpine:3.19
RUN apk --no-cache add curl ca-certificates
COPY --from=builder /server /usr/local/bin/server
# Health check: каждые 30 секунд, таймаут 5 секунд,
# 3 неудачи подряд = unhealthy
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD curl -f http://localhost:8080/healthz || exit 1
CMD ["/usr/local/bin/server"]
# Эндпоинт /healthz в Go-сервисе — проверяет реальную работоспособность
func healthzHandler(w http.ResponseWriter, r *http.Request) {
// Проверяем подключение к БД
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
if err := db.PingContext(ctx); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]string{
"status": "unhealthy",
"error": "database unreachable",
})
return
}
// Проверяем подключение к Redis
if err := rdb.Ping(ctx).Err(); err != nil {
w.WriteHeader(http.StatusServiceUnavailable)
json.NewEncoder(w).Encode(map[string]string{
"status": "unhealthy",
"error": "redis unreachable",
})
return
}
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
}
# docker-compose.yml с автоперезапуском
services:
api:
image: tasktracker-api
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/healthz"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 5
# Мониторинг состояния
# docker ps показывает статус: (healthy), (unhealthy), (starting)
# docker inspect --format='{{json .State.Health}}' tasktracker-api
start_period — время на запуск приложения, в течение которого неудачные проверки не считаются. Без него сервис, которому нужно 10 секунд на инициализацию, будет перезапущен раньше, чем успеет стартовать.
Оставить комментарий