With Docker's default json-file logging driver on Linux, each container's stdout and stderr are stored at /var/lib/docker/containers/<container-id>/<container-id>-json.log, where <container-id> is the full 64-character ID. In day-to-day use you read them with docker logs <container> rather than touching the file. On Docker Desktop (Mac/Windows) that path lives inside the Linux VM, not on your host, so docker logs is the only reliable way to read them. The driver is configurable globally in /etc/docker/daemon.json or per container with --log-driver.
Quick Reference: Docker Log Locations by Driver
| Logging driver | Where logs go | Readable with docker logs? |
|---|---|---|
json-file (default) | /var/lib/docker/containers/<id>/<id>-json.log | Yes |
local | /var/lib/docker/containers/<id>/local-logs/ (binary, rotated) | Yes |
journald | systemd journal (journalctl CONTAINER_NAME=<name>) | Yes |
syslog | host/remote syslog daemon | No |
fluentd | Fluentd collector endpoint | No |
awslogs | Amazon CloudWatch Logs | No |
gelf | Graylog/Logstash endpoint | No |
none | discarded | No |
Host-by-host data directory:
| Platform | Docker data root |
|---|---|
| Native Linux | /var/lib/docker/ |
| Docker Desktop (Mac) | inside the VM (~/Library/Containers/com.docker.docker/Data/...) |
| Docker Desktop (Windows, WSL2) | inside the WSL distro / VM disk |
| Rootless Docker | ~/.local/share/docker/ |
How to View and Tail Docker Logs
Follow a container's live output:
docker logs -f <container>
Show the last 100 lines with timestamps:
docker logs --tail 100 -t <container>
Only logs since a relative time:
docker logs --since 15m <container>
docker logs --since 2026-06-01T00:00:00 <container>
Compose stacks aggregate logs across services:
docker compose logs -f
docker compose logs -f web db
Find the raw file path on Linux:
docker inspect --format '{{.LogPath}}' <container>
Read the raw json-file directly (root required) and pretty-print:
sudo cat /var/lib/docker/containers/<id>/<id>-json.log | jq -r '.log'
For the journald driver:
journalctl CONTAINER_NAME=<name> -f
Finding Which Driver a Container Uses
The global default:
docker info --format '{{.LoggingDriver}}'
The driver for a specific container (it may differ from the default):
docker inspect --format '{{.HostConfig.LogConfig.Type}}' <container>
If this returns none or syslog/fluentd/awslogs, then docker logs will not work and you must read the destination system instead.
Native Linux Detail
Everything sits under /var/lib/docker/containers/. Each subdirectory is named after the full container ID and contains <id>-json.log plus rotated copies like <id>-json.log.1. These files are owned by root, so reading them directly requires sudo. Deleting a container with docker rm removes its log directory.
Docker Desktop Detail
Because the engine runs in a VM, /var/lib/docker is not visible from macOS Finder or Windows Explorer. To inspect the VM directly on Mac:
docker run -it --rm --privileged --pid=host justincormack/nsenter1
ls /var/lib/docker/containers/
In practice, just use docker logs — it proxies into the VM for you.
Changing the Logging Driver
Set the engine-wide default and rotation in /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
Apply with sudo systemctl restart docker. Existing containers keep their old config until recreated. Override per container at run time:
docker run --log-driver local --log-opt max-size=20m --log-opt max-file=5 myimage
In Compose:
services:
web:
image: myimage
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
Log Rotation
The json-file driver does not rotate logs unless you set max-size/max-file; a single chatty container can fill /var/lib/docker and take down the host. The local driver rotates and compresses automatically (default 20 MB, 5 files). You can also configure host logrotate, but the cleanest fix is max-size/max-file in daemon.json. Inspect current usage:
sudo du -sh /var/lib/docker/containers/*/*-json.log | sort -h | tail
Common Errors You'll Find in Docker Logs
Error: configured logging driver does not support reading— the container usessyslog,fluentd,gelf, orawslogs; read the destination system, notdocker logs.standard_init_linux.go: exec user process caused: no such file or directory— wrong architecture image or a missing interpreter/shebang in the entrypoint.OCI runtime create failed: ... permission denied— a mounted file or entrypoint script is not executable, or SELinux/AppArmor blocked it.no space left on device— the disk holding/var/lib/dockeris full, frequently from unrotated json logs or dangling images.container ... is not running— you randocker exec/logs -fagainst a container that already exited; checkdocker ps -aand exit codes.OOMKilledindocker inspectstate — the container exceeded its memory limit and the kernel killed it.
Troubleshooting: Logs Missing or Empty
- App logs to a file, not stdout —
docker logsonly captures stdout/stderr. Apps writing to a file inside the container won't appear; reconfigure the app to log to stdout or mount the file out. - Non-readable driver —
docker logserrors when the driver issyslog/fluentd/awslogs/none; checkHostConfig.LogConfig.Type. - Container removed —
--rmordocker rmdeletes the json file; the logs are unrecoverable. - Rotation pruned them —
max-filerotation discarded older lines; only the most recent files remain. - Permissions — reading
/var/lib/docker/containers/.../-json.logdirectly needs root. - Docker Desktop — the file path doesn't exist on the host; use
docker logs. - Buffered output — some runtimes buffer stdout; set
PYTHONUNBUFFERED=1(Python) or disable buffering so lines flush promptly.