Learn how to configure Docker health checks, inspect container health status, manage logs with docker logs, and choose the right log driver for production.
Health Checks and Logging
A running container is not necessarily a healthy container. Your web server might be up but unable to reach the database. Your worker process might be stuck in a crash loop. Docker health checks let you define exactly what "healthy" means for your application, and orchestrators like Docker Swarm and Kubernetes use that information to make routing and restart decisions. Logging is the companion story: once your containers are running, you need a way to understand what they are doing.
The HEALTHCHECK Instruction
The HEALTHCHECK instruction in a Dockerfile defines a command Docker runs periodically to probe whether the container is working correctly. If the command exits with status 0, that probe is healthy. If it exits with a non-zero status (1 is the convention for unhealthy; exit code 2 is reserved), that probe is a failure - but the container is only marked unhealthy after --retries consecutive failures (see below), and failures during the --start-period grace window do not count toward that total.
Syntax
Options
Examples
HTTP service health check:
PostgreSQL health check:
Redis health check:
Exposing a /health endpoint in Node.js
Your application should expose a dedicated health endpoint that checks its own dependencies:
A health endpoint that only checks if the HTTP server is up (but not whether the database is reachable) gives you a false sense of security. Check actual dependencies.
Inspecting Container Health
docker inspect JSON output for health:
The Log array contains the last five health check results. When debugging an unhealthy container, this is the first place to look.
Health Checks in Docker Compose
With condition: service_healthy, Compose waits for db to pass its health check before starting api. This solves the classic race condition where your application tries to connect to a database before it is ready.
Docker Logs
Every container captures the stdout and stderr of its main process. The docker logs command reads those captured streams.
Logs in Docker Compose
Log Drivers
By default, Docker captures container logs using the json-file driver, which stores logs as JSON on disk at /var/lib/docker/containers/<id>/<id>-json.log. This is convenient for docker logs, but it has limitations: no log rotation by default, no forwarding, and disk can fill up with verbose services.
Available log drivers
Configuring the log driver globally
Edit /etc/docker/daemon.json:
This configures log rotation: each log file caps at 10 MB, and Docker keeps the last 3 files (30 MB max per container). Restart the daemon after changes:
Configuring the log driver per container
Sending logs to AWS CloudWatch
Note: when you use a non-json-file or non-local driver, docker logs stops working because logs are no longer stored locally. This is a common gotcha - you must use your log aggregation system (CloudWatch console, Graylog, etc.) to view them.
Structured Logging Best Practices
For logs to be useful at scale, they must be structured (machine-readable) and consistent.
Use JSON log format in your application
JSON output (what Docker captures):
Log to stdout/stderr, not files
Containers are ephemeral. If your application writes logs to a file inside the container, those logs are lost when the container is removed. Always log to stdout (info/debug) and stderr (errors), and let Docker's log driver handle collection and forwarding.
Recommended fields for every log entry
Centralised Log Aggregation
For production environments with multiple containers, centralised logging is essential. Common stacks:
EFK Stack (Elasticsearch + Fluentd + Kibana):
Loki + Promtail + Grafana (lightweight alternative):
Loki with Promtail is particularly popular for Docker environments because Promtail can scrape Docker container logs directly via the Docker socket.
Summary
Observability is not optional in production. Health checks and structured logs are the minimum you need to know whether your application is running correctly and to diagnose problems when it is not.