Docker Compose Log Command: A Complete Debugging Guide
Disclosure: This post contains one or more links to providers we have a real, registered affiliate/referral relationship with. We may earn a commission at no extra cost to you if you sign up through them.
If your containers are misbehaving, the first place to look is the log output — and the docker compose logs command is how you get it. This guide covers everything from basic syntax to advanced filtering, log driver configuration, and shipping logs to a centralized platform for production monitoring.
Whether you’re running a single Compose stack on your laptop or a multi-service application in production, mastering the docker compose log workflow will save you hours of guesswork when something breaks.
This article assumes you already have Docker and Docker Compose installed and a working docker-compose.yml — if you’re setting up a stack from scratch, get the containers running first with docker compose up -d, then come back here once you need to actually read what they’re doing. Everything below works identically whether your compose file defines two services or twenty, and the same flags apply whether you’re debugging on a local dev machine or SSH’d into a remote host.
What Is the docker compose logs Command?
docker compose logs is a subcommand of the Docker Compose CLI that aggregates and displays the stdout/stderr output from every container defined in your docker-compose.yml file (or a specific service, if you name one). Unlike docker logs, which only works against a single container, docker compose logs understands your entire stack — it knows which containers belong to which project and can interleave their output with service-name prefixes so you can tell at a glance which container printed what.
This matters because most real applications aren’t a single container. A typical stack might include a web server, a database, a cache, and a background worker — four separate log streams that you’d otherwise have to tail individually with four terminal windows.
Basic Syntax and Options
The command follows this pattern:
docker compose logs [OPTIONS] [SERVICE...]
Run it with no arguments from the directory containing your docker-compose.yml and you’ll get the full log history for every service in the project:
docker compose logs
To scope it to one or more services, just name them:
docker compose logs web db
Following Logs in Real Time
Static output is useful for a quick check, but during active debugging you want a live stream. Use -f or --follow:
docker compose logs -f web
This behaves like tail -f — new log lines appear as they’re written, and the command keeps running until you press Ctrl+C. This is the single most-used flag in the docker compose logs toolkit, and it’s usually the first thing you run after docker compose up -d.
Filtering Logs by Service
When you’re running several services and only care about one, always scope by service name rather than grepping through the combined output:
docker compose logs -f --tail=100 api
You can also pass multiple service names at once to watch related containers together, which is handy when debugging an interaction between, say, a frontend proxy and its backend API.
Limiting Log Output with –tail
By default, docker compose logs prints the entire buffered history, which can be enormous for long-running containers. The --tail flag limits output to the last N lines:
docker compose logs --tail=50 web
Combine it with -f to see recent context and then continue following:
docker compose logs -f --tail=50 web
Advanced Log Filtering Techniques
Timestamps and Time Ranges
Add -t (or --timestamps) to prefix every line with an ISO 8601 timestamp — essential when correlating log events with an incident timeline:
docker compose logs -t web
To narrow output to a specific window, use --since and --until:
docker compose logs --since 2026-07-08T10:00:00 --until 2026-07-08T10:15:00 web
You can also use relative durations like --since 30m or --since 2h, which is often faster than typing out a full timestamp when you’re chasing something that just happened.
Combining Logs with grep
docker compose logs doesn’t have a built-in search flag, but because it writes to stdout, you can pipe it straight into standard Unix tools:
docker compose logs --no-color web | grep -i "error"
The --no-color flag strips ANSI color codes so your grep matches aren’t broken up by escape sequences. This pattern — Compose logs piped into grep, awk, or jq (for JSON-formatted app logs) — covers the vast majority of manual debugging you’ll ever need to do.
Handling Logs for Scaled Services
If you’re running multiple replicas of a service with docker compose up --scale worker=3, docker compose logs worker interleaves output from all three containers, each prefixed with its own container name so you can tell them apart. This is useful for spotting whether a bug affects every replica or just one — a single misbehaving replica often points to a stuck connection or a stale cache entry rather than a code bug. If you need to isolate a single replica’s output, use docker ps to find its container ID and switch to plain docker logs <container_id> instead.
Configuring Log Drivers in Docker Compose
By default, Docker uses the json-file logging driver, which writes each container’s output to a JSON file on disk. That’s fine for development, but it has two problems in production: unbounded log files can fill your disk, and json-file logs disappear if the host is replaced.
You can configure log rotation and an alternate driver per service directly in your docker-compose.yml:
services:
web:
image: myapp:latest
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
This caps each container’s log file at 10 MB and keeps a maximum of 3 rotated files, which prevents runaway disk usage — a surprisingly common cause of production outages that has nothing to do with your application code.
For teams that need durable, searchable logs, switching to a shipping-friendly driver like journald or syslog, or running a sidecar log forwarder, is the next step. That’s a bigger topic than this article can fully cover, but if you’re already tuning Docker networking for multi-container apps, log driver configuration belongs in the same pass.
Centralizing Logs for Production
docker compose logs is a local debugging tool — it reads whatever the log driver has retained on that specific host. That’s a real limitation once you’re running more than one server, since logs vanish when a container is removed or a host is rebuilt. For production stacks, you want logs shipped somewhere durable and searchable.
A few practical options:
docker compose logs -f as your primary debugging tool.If you’re just getting started with Compose in general, our Docker Compose restart policies guide is a good companion piece — restart behavior and logging are usually the first two things you tune once a stack graduates from “works on my machine” to “runs in production.”
For the official reference on every driver and option, the Docker documentation on logging drivers covers configuration syntax that’s easy to get subtly wrong, particularly around driver-specific options that Compose passes through without validation.
Rotating Logs Automatically
Log rotation deserves its own callout because it’s the most commonly skipped step. Without max-size and max-file set, json-file logs grow forever. On a busy service, that can mean gigabytes of logs eating disk space within days. Add rotation to every service in your Compose file, not just the noisy ones — the quiet services are the ones nobody remembers to check until the disk is full.
Using docker compose logs in CI/CD Pipelines
CI runners are another place docker compose logs earns its keep. When an integration test fails inside a containerized service, the test runner has usually already exited before you can attach a terminal. The fix is to dump logs as a post-failure step in your pipeline configuration, for example in a GitHub Actions job:
- name: Dump logs on failure
if: failure()
run: docker compose logs --no-color > compose-output.log
Running this on failure means you get the full container output attached to the CI job log, instead of a bare “test failed” message with no context. This one habit saves more debugging time than almost any other logging practice on this list.
Common Issues and Troubleshooting
A few problems come up often enough to call out specifically:
docker-compose.yml, or you’re running the command from the wrong directory. docker compose logs only sees services defined in the compose file in your current working directory (or the one passed via -f).none or a non-default driver like syslog without local buffering, docker compose logs won’t have anything to show, since it reads from the driver’s local output, not the application directly.--no-color when piping into grep, awk, or a file.Comparing docker logs vs docker compose logs
It’s worth being explicit about the difference, since the two commands look similar but aren’t interchangeable:
docker logs my_container_1
docker compose logs my_service
docker logs operates on a single container by name or ID and knows nothing about Compose projects. docker compose logs operates on services defined in your compose file and can span multiple containers per service if you’re running replicas. If you only remember one rule, remember this: use docker compose logs when you’re thinking in terms of your application’s services, and docker logs when you’re debugging one specific container instance.
Recommended: Ready to put this into practice? DigitalOcean is a tool we use for exactly this, and we have a real, disclosed affiliate relationship with them.
FAQ
Q: How do I see logs for only one service in a multi-service Compose stack?
A: Pass the service name as an argument: docker compose logs web. You can list multiple service names separated by spaces to watch several at once.
Q: How do I follow logs in real time?
A: Add the -f or --follow flag: docker compose logs -f. Press Ctrl+C to stop following.
Q: Why does docker compose logs show no output at all?
A: Usually because the container isn’t running, the log driver is set to something that doesn’t retain local output (like none), or you’re running the command outside the directory containing your docker-compose.yml.
Q: Can I export docker compose logs to a file?
A: Yes — redirect stdout: docker compose logs --no-color > app.log. Use --no-color first so the file doesn’t contain ANSI escape codes.
Q: How do I limit how much log history is shown?
A: Use --tail=N to show only the last N lines per service, or --since to restrict output to a time window.
Q: Does docker compose logs work after a container has stopped?
A: Yes, as long as the container hasn’t been removed. Docker retains the log file for stopped containers until they’re deleted with docker compose down or docker rm.
Wrapping Up
The docker compose logs command is the fastest path from “something’s wrong” to “here’s why.” Start with -f and --tail for everyday debugging, add --since and -t when you need to correlate events with a timeline, and don’t skip log rotation once you’re running anything in production. When local log files stop being enough, that’s your signal to invest in centralized, searchable logging rather than scrolling through terminal history.
Leave a Reply