docker compose logs is the command you’ll run every time something breaks in a multi-container stack. It aggregates logs from all your services into one stream — or lets you filter to exactly the container you need.

This guide covers every flag, practical debugging patterns, and how to pipe Docker logs into a proper log management system.

Basic Usage

# Print logs from all services (last output)
docker compose logs

# Follow logs in real time (like tail -f)
docker compose logs -f

# Show logs from a specific service
docker compose logs web

# Follow a specific service
docker compose logs -f web

By default, docker compose logs shows all output collected since the containers started, which can be thousands of lines. The flags below let you control that.

Essential Flags

—follow / -f

Stream logs in real time. The command stays open and prints new log lines as they arrive:

docker compose logs -f

Press Ctrl+C to stop following. The containers keep running — you’re only disconnecting from the log stream.

—tail

Limit how many recent lines are shown. Without this, you get the full log history:

# Last 50 lines from all services
docker compose logs --tail 50

# Last 100 lines, then follow new output
docker compose logs -f --tail 100

# Last 20 lines from the database service
docker compose logs --tail 20 db

--tail 0 shows no historical output — only new lines from this point forward. Useful when you want to monitor a service without scrolling through startup logs.

—timestamps / -t

Prepend UTC timestamps to every log line:

docker compose logs -t
docker compose logs -f -t --tail 50

Without -t, you see raw log output with no timing information. With -t, each line starts with the container’s UTC timestamp — different from your local timezone unless you’ve configured TZ in your containers.

—since and —until

Filter logs by time range:

# Logs from the last 5 minutes
docker compose logs --since 5m

# Logs from the last 2 hours
docker compose logs --since 2h

# Logs since a specific timestamp
docker compose logs --since "2026-06-24T10:00:00"

# Logs between two timestamps
docker compose logs --since "2026-06-24T09:00:00" --until "2026-06-24T10:00:00"

Time durations use Go’s duration syntax: s (seconds), m (minutes), h (hours).

—no-color

Disable ANSI color codes. Useful when piping output to a file or a log processor:

docker compose logs --no-color > logs.txt

—no-log-prefix

By default, each line is prefixed with the service name and container number:

web-1  | 2026/06/24 10:00:00 Server started on :8080
db-1   | 2026-06-24 10:00:01 database system is ready to accept connections

--no-log-prefix removes the prefix, leaving clean output:

docker compose logs --no-log-prefix web

Useful when piping a single service’s logs to another tool.

Filtering to a Specific Service

Pass service names as arguments — you can specify multiple:

# Single service
docker compose logs web

# Multiple services
docker compose logs web db

# Follow two services simultaneously
docker compose logs -f web worker

Service names must match exactly what’s in your docker-compose.yml.

Combining Flags for Real-World Debugging

Debug a startup failure

Your container exited immediately and you need to see why:

docker compose logs --tail 50 web

Monitor a deployment in progress

Watch all services as a new version comes up:

docker compose logs -f --tail 0

--tail 0 means “start from now” — you skip all the historical startup logs.

Find errors in the last hour

docker compose logs --since 1h | grep -i error

Show the last 100 lines with timestamps

docker compose logs -t --tail 100 web

Save logs to a file for analysis

docker compose logs --no-color --since 24h > debug_$(date +%Y%m%d).log

Understanding Docker Logging Drivers

Docker Compose inherits Docker’s logging driver configuration. The default driver is json-file, which writes logs to /var/lib/docker/containers/<id>/<id>-json.log on the host.

The docker compose logs command reads these JSON files and formats them for terminal output.

Limiting log file size

By default, Docker keeps unlimited logs. On a busy server, this fills your disk. Set limits in your compose file:

services:
  web:
    image: nginx
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

This keeps at most 3 files of 10 MB each per container — 30 MB maximum per service.

Switching logging drivers

For production, consider forwarding logs to a centralized system instead of storing them locally:

services:
  web:
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://logs.yourdomain.com:514"

Other supported drivers: journald, fluentd, awslogs, splunk, gcplogs.

Important: When you use a non-json-file driver, docker compose logs returns no output because the local log files don’t exist. All log access must go through the external system.

Grepping Docker Logs

Docker Compose doesn’t have a built-in filter. Use standard Unix tools:

# Find all lines containing "ERROR"
docker compose logs --no-color | grep ERROR

# Case-insensitive search
docker compose logs --no-color | grep -i "connection refused"

# Show 5 lines of context around each match
docker compose logs --no-color | grep -C 5 "panic"

# Count errors per service
docker compose logs --no-color --since 1h | grep "ERROR" | cut -d'|' -f1 | sort | uniq -c

Real-Time Log Monitoring with BetterStack

For production stacks, shipping logs to a managed platform removes the need to SSH into your server every time something breaks. BetterStack Logs integrates with Docker directly and provides full-text search, alerting, and dashboards.

Set it up in your compose file:

services:
  web:
    image: your-app
    logging:
      driver: json-file   # keep this for docker compose logs to work locally
      options:
        max-size: "10m"
        max-file: "5"

Then run the BetterStack vector agent as a separate container that reads Docker log files and forwards them. BetterStack’s free tier handles up to 1 GB/month — enough for a small production stack.

Structured Logging

If your application emits JSON logs, Docker Compose still shows them as raw strings. For human-readable output in development:

# Pretty-print JSON logs from a Node.js app using jq
docker compose logs --no-log-prefix web | jq .

Or if your app uses pino or bunyan:

docker compose logs --no-log-prefix web | npx pino-pretty

Multi-File Compose Logging

If you use multiple compose files:

docker compose -f docker-compose.yml -f docker-compose.prod.yml logs -f web

The -f file flags must come before the logs subcommand.

Logs in Detached Mode

When you start a stack with docker compose up -d, logs go to the Docker daemon and are accessible via docker compose logs at any time.

For interactive debugging sessions where you want logs in the terminal:

# Start the stack interactively (Ctrl+C stops everything)
docker compose up

# Start in background, then attach to logs
docker compose up -d
docker compose logs -f

Checking Logs After a Container Crash

If a container has already exited, docker compose logs still shows its output as long as the container hasn’t been removed:

# Show logs from a crashed container
docker compose logs web

# Confirm the container exited and its exit code
docker compose ps -a

After docker compose down, the container is removed and its logs are gone. Always check logs before running down.

VPS Disk Space and Log Management

On a VPS, Docker log files accumulate fast. Check their size:

du -sh /var/lib/docker/containers/*/

If logs are eating your disk, prune them:

# Truncate log files for all containers (Docker built-in)
docker system prune --volumes

# Or truncate a specific container's log file
truncate -s 0 /var/lib/docker/containers/<container-id>/*-json.log

Better long-term: configure max-size in your compose file from the start.

If you need a VPS with generous disk space for running Docker workloads, Hetzner Cloud offers 40 GB NVMe SSD on their €4.15/month plan — plenty for most stacks. New accounts receive €20 free credits. For US-based workloads, DigitalOcean starts at $6/month with $200 free credits.

Quick Reference

GoalCommand
View all logsdocker compose logs
Follow livedocker compose logs -f
Last N linesdocker compose logs --tail N
With timestampsdocker compose logs -t
Specific servicedocker compose logs web
Last hourdocker compose logs --since 1h
Save to filedocker compose logs --no-color > out.log
No prefixdocker compose logs --no-log-prefix web

Summary

docker compose logs is your primary debugging tool for containerized stacks. For day-to-day use, docker compose logs -f --tail 100 <service> covers 90% of cases. Set max-size and max-file in your compose files to prevent disk exhaustion, and consider a managed log platform for production environments where you need search, alerting, and retention.