docker compose logs shows the output that services write to standard output and standard error. Run it with a service name for a focused view, or without one to combine output from the current Compose project.
Start with a bounded command that includes timestamps:
docker compose logs --tail 100 --timestamps api
Then follow new output while reproducing the problem:
docker compose logs --tail 20 --follow --timestamps api
The command is an inspection tool, not a retention policy. Its available history depends on the containers, Docker logging configuration, and rotation that already exist on that host.
Docker Compose logs commands worth keeping
The current Docker Compose logs reference defines these options. The examples below were also checked against Docker Compose 5.5.1; use docker compose version and docker compose logs --help before copying them into a runbook for an older installation.
| Task | Command |
|---|---|
| Show all services | docker compose logs |
| Show one service | docker compose logs api |
| Show selected services | docker compose logs api worker |
| Follow new output | docker compose logs --follow api |
| Show the last 100 lines per container | docker compose logs --tail 100 |
| Add timestamps | docker compose logs --timestamps |
| Show a recent time window | docker compose logs --since 15m api |
| Stop at a time boundary | docker compose logs --until 2026-09-15T18:00:00Z api |
| Remove color codes | docker compose logs --no-color api |
| Remove service prefixes | docker compose logs --no-log-prefix api |
| Select one replica | docker compose logs --index 2 worker |
--tail applies to each container, so --tail 100 across six containers can return as many as 600 lines. Combine it with one or more service names when a broad view is too noisy.
--since and --until accept timestamps or relative durations in the current CLI. For an incident record, absolute UTC timestamps make the window reproducible:
docker compose logs \
--since 2026-09-15T17:45:00Z \
--until 2026-09-15T18:00:00Z \
--timestamps \
api worker
Timestamps help compare services, but interleaved container output is not a globally ordered distributed trace. Clock skew, buffering, and concurrent writes can still affect the sequence you see.
Follow new lines without losing startup context
--follow alone starts a live stream after Compose displays the available backlog. Bound that initial output with --tail:
docker compose logs --tail 50 --follow --timestamps api
Stop the command with Ctrl+C; that stops the viewer, not the containers. Use --until when a capture should end at a defined boundary:
docker compose logs \
--follow \
--since 10m \
--until 2026-09-15T18:30:00Z \
api
Avoid piping a live stream through a filter until you have first confirmed the unfiltered service and time window. Shell tools can buffer output, hide context, or match secrets that should not be copied elsewhere.
Keep prefixes unless another field identifies the source
Compose prefixes merged output with the service and container source. --no-log-prefix removes that context. It can make single-service output cleaner, but it makes multi-service output ambiguous unless every application record already includes a reliable service and instance field.
--no-color removes terminal color codes and is useful before controlled processing or attachment to an incident record. It does not redact credentials, personal data, or application payloads.
Scope logs to the correct project and files
Compose discovers a project from the working directory, Compose files, environment, and project-name rules. Running the same command from another directory can select a different project or find none.
The root docker compose command accepts -f for configuration files, -p for the project name, and --project-directory for the project directory. These options go before logs:
docker compose \
-f compose.yaml \
-f compose.production.yaml \
-p storefront \
logs --tail 100 api
Multiple -f files are applied in order. Use the same file order and project name that created the containers. The Compose command reference also notes that the project directory defaults from the first specified Compose file unless --project-directory overrides it.
For a script or runbook, make that directory explicit:
docker compose \
--project-directory /srv/storefront \
-f /srv/storefront/compose.yaml \
-p storefront \
logs --since 15m api
Project scoping prevents two similarly named stacks from being mistaken for each other. It does not combine logs across Docker hosts; the command talks to the selected Docker daemon.
Choose a service or replica deliberately
A Compose service can have several replicas. Without --index, logs for that service can include every replica. Use the service name plus --index when one container is the subject:
docker compose logs --index 2 --tail 100 --timestamps worker
First inspect the project containers:
docker compose ps --all --format json
The current docker compose ps reference states that only running containers appear by default. --all adds stopped containers, including containers created by docker compose run, and --format json emits machine-readable records.
Do not assume replica index 2 is the failed container merely because a container name ends in -2. Confirm its service, state, and identity from compose ps, then use the index supported by compose logs.
Find why Docker Compose logs is empty
An empty result does not prove that the application produced no events. Check the path in this order.
1. Confirm the applied Compose model
Validate without printing interpolated configuration:
docker compose -f compose.yaml -p storefront config --quiet
When authorized to inspect the resolved configuration, run:
docker compose -f compose.yaml -p storefront config
docker compose config parses, resolves, and renders the Compose model in canonical form. This reveals merged files, interpolation, service names, logging settings, and enabled configuration. Its output can contain resolved environment values or sensitive paths, so do not paste it into a ticket without review.
The rendered model describes intended Compose configuration. It does not prove that existing containers were recreated after a change or that the daemon default matches the file.
2. Check running and stopped containers
docker compose ps --all --format json
Look for the expected service, container state, exit code, and health state. If no container exists in the selected project, compose logs has nothing to read. If a previous container was removed and replaced, its local history does not automatically move into the replacement.
3. Confirm the process writes to stdout or stderr
Docker logging drivers capture a container process's standard output and standard error. A service that writes only to an internal file does not appear in docker compose logs. Either configure the application or a sidecar to forward that file to stdout or stderr, or collect the file separately into the central log backend through a supported collector. The second path does not make the file visible to compose logs.
Application buffering can delay otherwise valid output. Configure the runtime's supported flush or unbuffered mode rather than adding arbitrary shell wrappers. Confirm that startup, error, and shutdown paths all use the configured logger.
4. Check the logging driver through Docker
Use the earlier docker compose ps --all --format json output to choose one container whose project, service, replica, and state you have verified. Copy that container's exact ID, then inspect it through the Docker API, replacing VERIFIED_CONTAINER_ID below:
docker inspect --format '{{.HostConfig.LogConfig.Type}}' VERIFIED_CONTAINER_ID
The driver may be inherited from the daemon or set in the service configuration. Docker documents dual logging for drivers that cannot read their own logs: Docker automatically adds a local cache so docker logs and docker compose logs can still read recent output. Disabling that cache can make both commands unavailable with those drivers. The readable local, json-file, and journald drivers do not use this automatic dual-logging cache, while the none driver intentionally provides no logs.
Never open, tail, truncate, move, or parse Docker's internal log files directly. Docker's local logging-driver documentation says those files are for exclusive daemon access and external interaction can interfere with the logging system.
5. Check the requested window and available history
Remove --since and --until, then try a small --tail against one known service. If new lines appear but older ones do not, inspect the configured rotation and whether the container was recreated. compose logs cannot recover records already rotated away or held only by a removed container.
Use events for lifecycle changes, not application output
docker compose events reports container lifecycle activity such as creation, start, stop, and other Docker events. It does not replace application logs.
docker compose events --json
The current Compose events reference documents --json, --since, and --until. Use an explicit window when comparing restarts with application failures:
docker compose events \
--json \
--since 2026-09-15T17:45:00Z \
--until 2026-09-15T18:00:00Z
Use compose events to establish that a container stopped or restarted. Use compose logs to read what the process wrote before or after that lifecycle change. Neither command proves the root cause by itself.
Keep Docker logs bounded on disk
Docker Engine uses the json-file logging driver by default for compatibility, and the current logging-driver configuration guide warns that it performs no rotation by default. A verbose container can therefore consume substantial disk unless rotation is configured.
Docker recommends the local driver outside compatibility cases because it rotates by default and uses a more efficient internal format. Its documented defaults preserve up to five files of 20 MB each per container and compress rotated files, for a nominal 100 MB before accounting for implementation details.
Make a service-level policy explicit in Compose:
services:
api:
image: registry.example.com/storefront-api:1.8.4
logging:
driver: local
options:
max-size: "20m"
max-file: "5"
compress: "true"
This is a configuration change. Review the disk budget and incident-history requirement before applying it. A smaller limit reduces disk exposure but removes old local evidence sooner. The change takes effect for a newly created container; schedule any recreation safely and preserve needed evidence first.
Changing the daemon default affects only new containers
The equivalent daemon default is:
{
"log-driver": "local",
"log-opts": {
"max-size": "20m",
"max-file": "5",
"compress": "true"
}
}
Changing daemon configuration and restarting Docker are state-changing operations. Validate the full daemon configuration, obtain approval, and use the platform's maintenance procedure. Docker states that a changed default applies only to newly created containers; existing containers do not adopt it automatically.
Do not change the driver only to make compose logs prettier. Check compatibility with the runtime, host management, collectors, and recovery requirements first.
Make application output readable before centralizing it
Compose adds a source prefix, but it does not turn free-form text into structured application logs. Prefer one JSON object per logical event with stable fields:
{"timestamp":"2026-09-15T17:51:23Z","severity":"ERROR","service":"api","event":"order.persist_failed","request_id":"req_example_7f3a","message":"Database transaction failed","release":"1.8.4"}
Treat that line as a synthetic example; field names and timestamps depend on the application and collector. Do not log authorization headers, cookies, connection strings, request bodies, personal data, or secrets. Sanitize untrusted carriage returns and line feeds so an attacker cannot forge additional log lines.
Keep service, release, environment, event name, request ID, and safe error type in separate fields. Those fields remain useful whether the immediate viewer is a terminal or a centralized backend. Microservices logging architecture covers schemas and cross-service correlation in more depth.
Centralize Compose logs when the host is no longer enough
docker compose logs is effective for one project on one Docker daemon. A central pipeline is needed when history must survive container replacement, operators need one search across hosts, alerts depend on retained events, or access must be shared without Docker daemon privileges.
Use this boundary:
container stdout/stderr
-> Docker logging subsystem
-> supported collector or logging-driver integration
-> authenticated encrypted transport
-> central backend
-> search, Live Tail, alerts, retention
Use a documented collector or driver integration rather than scripts that read Docker's internal files. Set bounded queues, disk buffering, retries, and an explicit overflow policy. Monitor rejected or dropped records and destination freshness; centralization does not create evidence that the source discarded before transmission.
The Docker container logging guide covers the broader collection path, while log management best practices covers retention, access, and pipeline health.
Send retained Docker logs to Fluxtail
Fluxtail is a paid, logs-focused service with self-service Starter and Pro plans. A supported collector can forward container output through a configured Fluxtail receiver, which routes accepted records into simple named streams. Operators can then use Live Tail, search, filters, and alerts without granting direct Docker daemon access.
Collector parsing determines how the original Docker record becomes Fluxtail message, service, severity, labels, and container fields. Verify one unique event in Live Tail before relying on any mapped field for filters or alerts. Keep local queue, retry, and overflow behavior in the collector runbook.
Fluxtail's built-in AI chat and hosted MCP are separate investigation paths. Hosted MCP uses OAuth with PKCE, binds access to one account, and applies the underlying account permissions. Raw events remain the evidence, and stream or receiver mutations require a proposal followed by a short-lived confirmation step.
For a shareable browser view, see Fluxtail Live Tail. Create a Fluxtail account when Compose output needs retained search and alerting beyond one Docker host.