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
- Define health checks: For all critical services
- Use a start period: Give the application time to start
- Short timeouts: Avoid checks that take too long
- Enough retries: 3-5 retries to avoid false positives
- 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.