Learn how to configure logging in Docker Compose — JSON file driver, log rotation, structured output, and shipping logs to a centralized service.
Docker Compose is the standard way to run multi-container applications locally and in production. But the default logging setup — dumping everything to JSON files with no rotation — fills your disk and makes debugging impossible across services.
Here's how to set up production-ready logging for Docker Compose.
Docker's default logging driver (json-file) writes every container's stdout/stderr to a JSON file at /var/lib/docker/containers/<id>/<id>-json.log. These files:
docker compose down (if using anonymous volumes)# Finding logs for a specific container
docker compose logs api | grep error
# This works for one container. With 8 services, good luck.
Always set log rotation. Without it, a busy container will fill your disk:
# docker-compose.yml
services:
api:
image: myapp/api
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
This keeps at most 30 MB of logs per container (3 files × 10 MB). Apply it to every service.
To set a default for all services, add to your Docker daemon config (/etc/docker/daemon.json):
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Docker captures stdout/stderr. If your app prints structured JSON, Docker preserves it:
// Node.js — output JSON to stdout
const { LogFlow } = require('@getlogflow/js')
const logger = new LogFlow({ apiKey: process.env.LOGFLOW_API_KEY, service: 'api' })
logger.info('request.handled', { path: '/api/users', status: 200, duration_ms: 45 })
# Python — JSON to stdout
import json, sys
def log(level, message, **kwargs):
entry = {"level": level, "message": message, "service": "worker", **kwargs}
print(json.dumps(entry), file=sys.stdout, flush=True)
log("info", "job.completed", job_id="JOB-123", duration_ms=1200)
See our guides for structured logging and framework-specific setup: Express, FastAPI, Django.
Docker Compose automatically sets labels that identify the service. Use them for filtering:
services:
api:
image: myapp/api
labels:
com.logflow.service: "api"
com.logflow.environment: "production"
worker:
image: myapp/worker
labels:
com.logflow.service: "worker"
com.logflow.environment: "production"
Log shippers like Fluent Bit and Vector can read these labels and add them to every log line.
Local docker compose logs doesn't scale. You need a centralized system. Three approaches:
If you control the application code, send logs directly from inside the container:
const { LogFlow } = require('@getlogflow/js')
const logger = new LogFlow({
apiKey: process.env.LOGFLOW_API_KEY,
service: 'api',
})
Pass the API key as an environment variable in docker-compose.yml:
services:
api:
image: myapp/api
environment:
- LOGFLOW_API_KEY=${LOGFLOW_API_KEY}
This is the fastest path. See the quickstart guide.
Add Fluent Bit as a service in your Compose file to collect logs from all containers:
services:
fluent-bit:
image: fluent/fluent-bit:latest
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
depends_on:
- api
- worker
# fluent-bit.conf
[INPUT]
Name tail
Path /var/lib/docker/containers/*/*.log
Parser docker
Docker_Mode On
Refresh_Interval 5
[OUTPUT]
Name http
Match *
Host api.getlogflow.com
Port 443
URI /v1/logs
Header Authorization Bearer lf_your_api_key
Format json
tls On
Use Docker's built-in fluentd or syslog logging driver to forward logs:
services:
api:
image: myapp/api
logging:
driver: fluentd
options:
fluentd-address: "localhost:24224"
tag: "docker.api"
This redirects stdout/stderr at the Docker level — no application changes needed.
Health checks ensure Docker restarts unhealthy containers and help you track uptime:
services:
api:
image: myapp/api
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
Health check events appear in Docker logs. Combined with anomaly detection, you get automatic alerts when services go unhealthy.
While setting up centralized logging, docker compose logs is your local debugging tool:
# Follow logs from all services
docker compose logs -f
# Follow specific service
docker compose logs -f api
# Last 100 lines from all services
docker compose logs --tail=100
# Since a specific time
docker compose logs --since="2026-08-22T10:00:00"
# Filter with grep
docker compose logs api 2>&1 | grep "error"
Before deploying a Docker Compose application:
max-size, max-file)Free plan available. No credit card required. Up and running in 2 minutes.
Get started freePython Logging Best Practices in 2026
Stop using print() for debugging. Here's how to set up production-ready logging in Python with the standard library and beyond.
What Is Centralized Logging? A Complete Guide
Centralized logging collects logs from every server, container, and service into one searchable place. Here's everything you need to know.
7 ELK Stack Alternatives for Log Management in 2026
Elasticsearch, Logstash, and Kibana are powerful but expensive to operate. Here are 7 alternatives that don't need a platform team.