Skillversitas

Docker Health Checks

Health checks allow Docker to monitor container health and take action when needed.

Defining a Health Check

# In the Dockerfile
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

Health Check Options

# Interval: time between checks
HEALTHCHECK --interval=30s

# Timeout: maximum time for a check
HEALTHCHECK --timeout=3s

# Retries: number of attempts before unhealthy
HEALTHCHECK --retries=3

# Start period: time before the first check
HEALTHCHECK --start-period=10s

# Combined
HEALTHCHECK --interval=30s --timeout=3s --retries=3 --start-period=10s \
  CMD curl -f http://localhost/health || exit 1

Health Check Examples

HTTP Check

HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:3000/health || exit 1

TCP Check

HEALTHCHECK --interval=30s --timeout=3s \
  CMD nc -zv localhost 5432 || exit 1

Command Check

HEALTHCHECK --interval=30s --timeout=3s \
  CMD node -e "process.exit(0)" || exit 1

Health Checks in Docker Compose

version: '3.8'

services:
  api:
    build: ./backend
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 10s

  database:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5

Checking Health Status

# View the health status
docker inspect --format='{{.State.Health.Status}}' api

# View the health check log
docker inspect --format='{{json .State.Health}}' api | jq

# View the status of all containers
docker ps
# The STATUS column shows the health status

Use Case: Application Health Checks

# Backend API
FROM node:18-alpine

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .

HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "server.js"]
# docker-compose.yml
version: '3.8'

services:
  api:
    build: ./backend
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 10s
    depends_on:
      database:
        condition: service_healthy

  database:
    image: postgres:15
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5

Everyday Use Case

Case: A developer needs to make sure the application is running.

# Check the health status
docker ps

# View health details
docker inspect --format='{{.State.Health.Status}}' api

# View the health check log
docker logs api 2>&1 | grep health

Best Practices

  1. Define health checks: For all critical services
  2. Use a start period: Give the application time to start
  3. Short timeouts: Avoid checks that take too long
  4. Enough retries: 3-5 retries to avoid false positives
  5. depends_on with condition: Use service_healthy

Troubleshooting

Container is always unhealthy

# Check the application logs
docker logs api

# Check the health check log
docker inspect --format='{{json .State.Health}}' api | jq

# Test the health check manually
docker exec api curl -f http://localhost:3000/health

Health check timeout

# Add a timeout
HEALTHCHECK --timeout=10s

# Or reduce the check complexity
HEALTHCHECK CMD curl -f http://localhost/health || exit 1

Conclusion

Health checks ensure that the application is running correctly. Use health checks for all critical services in your application.