Docker Health Check — Is Your Container Actually Working?
What Is a Docker Health Check in Simple Terms?
A container can be running without actually working. PostgreSQL might be up but still initialising. Your API might be running but stuck in a deadlock. A health check is a command Docker runs periodically inside the container — if it succeeds (exit code 0), the container is healthy. If it fails repeatedly, Docker marks it as unhealthy.
Orchestrators use health status for routing — Kubernetes does not send traffic to pods that are not healthy.
◈ DIAGRAM
+------------------------------------------+| Container starts || Status: starting |+------------------------------------------+ | (after start_period) | | health check runs (every interval) | v+------------------------------------------+| Exits 0 repeatedly -> healthy || Exits non-0 repeatedly -> unhealthy |+------------------------------------------+HEALTHCHECK in Dockerfile
Dockerfile
# HTTP endpoint checkHEALTHCHECK --interval=30s --timeout=5s \ --start-period=15s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # wget (available in Alpine, no curl needed)HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider \ http://localhost:8080/health || exit 1 # Parameters:# --interval How often to run (default: 30s)# --timeout Max time for check to complete (default: 30s)# --start-period Grace period before first check (default: 0s)# --retries Failures before unhealthy (default: 3)Health Check Commands by Service
Dockerfile
# PostgreSQLHEALTHCHECK CMD pg_isready -U postgres -d mydb || exit 1 # RedisHEALTHCHECK CMD redis-cli ping | grep -q PONG || exit 1 # MySQLHEALTHCHECK CMD mysqladmin ping -h localhost || exit 1 # RabbitMQHEALTHCHECK --start-period=30s \ CMD rabbitmq-diagnostics ping || exit 1 # Custom application checkHEALTHCHECK CMD node /app/scripts/healthcheck.js || exit 1Monitoring Health Status
Bash
# See health status in docker psdocker ps# NAME STATUS# payment-api Up 5m (healthy)# postgres Up 5m (healthy)# redis Up 2m (unhealthy) <- problem! # See health check logs for unhealthy containerdocker inspect redis \ --format '{{json .State.Health}}' | jq# {# "Status": "unhealthy",# "FailingStreak": 3,# "Log": [{# "ExitCode": 1,# "Output": "Could not connect to Redis"# }]# }# The Output field tells you exactly why the check is failing # In Docker Compose — use with depends_onservices: api: depends_on: postgres: condition: service_healthy # waits for healthy statusPLACEMENT PRO TIP**Tip:** The `start_period` parameter is critical for services that take time to initialise. Set it to the maximum time your service needs to start — typically 10s for web services and 30s for databases. Without `start_period`, health check failures during normal startup count toward the failure threshold and can mark healthy services as unhealthy.