π Day 11: Deep Dive into Docker Containers Logging: From Basic to Advanced π³

Table of contents
- π Introduction to Docker Logging
- π€ Why Logging Matters?
- π οΈ Basics of Docker Container Logs
- stdout vs stderr
- π Docker help command
- β Syntax Examples
- π§ͺ LAB Activity
- π³ Docker Logging Lab: Inspecting Container Logs with container name, image name and id in logs π
- πDefault Logging Driver: json-file
- βοΈ Setting/Changing Logging Drivers Globally π
- π¦ Set directly log drivers to specific containers to override global config
- π³ Docker Logging Drivers Overview: Customizing Logging Drivers
- π Supported Logging Drivers
- π Set driver at runtime:
- π GUI Logging APP 1
- π GUI Logging APP 2
- π GUI Logging APP 3
- π How to Properly Log (Best Practices)
- π― Summary
- π³ Docker Logging Resources

This guide explores Docker container logging in depth, covering everything from basic concepts to advanced production-grade strategies. Perfect for creating a comprehensive YouTube video on Docker logs! π₯
π Introduction to Docker Logging
Docker containers generate logs to track their activities, errors, and runtime behavior. These logs are essential for debugging, monitoring, and ensuring the health of applications in development and production environments. Docker provides a flexible logging system that can be tailored to various use cases. Let's dive into the fundamentals and scale up to advanced techniques! π
π€ Why Logging Matters?
Debugging: Identify and fix issues in containerized applications.
Monitoring: Track performance and system health.
Auditing: Maintain records for compliance and security.
Troubleshooting: Pinpoint failures in production systems.
π οΈ Basics of Docker Container Logs
Docker captures logs from a containerβs stdout
(standard output) and stderr
(standard error) streams. By default, Docker uses the json-file
logging driver to store logs.
stdout
vs stderr
Stream | Purpose |
stdout | Standard output (normal messages) |
stderr | Standard error (error messages) |
stdout
is for successful output.stderr
is for errors and warnings.
[!attention] In Docker logs both
stdout
vsstderr
is combined, to see separately see below examples
π Docker help command
Get options using help command.
docker container logs --help
Usage: docker container logs [OPTIONS] CONTAINER
Fetch the logs of a container
Aliases:
docker container logs, docker logs
Options:
--details Show extra details provided to logs
-f, --follow Follow log output
--since string Show logs since timestamp (e.g. "2013-01-02T13:23:37Z") or relative
(e.g. "42m" for 42 minutes)
-n, --tail string Number of lines to show from the end of the logs (default "all")
-t, --timestamps Show timestamps
--until string Show logs before a timestamp (e.g. "2013-01-02T13:23:37Z") or relative
(e.g. "42m" for 42 minutes)
β Syntax Examples
docker logs --follow <container_name_or_id>
docker logs --details <container_name_or_id>
docker logs --timestamps <container_name_or_id>
docker logs --tail <number> <container_name_or_id>
docker logs --tail 5 <container_name_or_id>
docker logs --tail 5 --follow <container_name_or_id>
docker logs <container_id> --since YYYY-MM-DD
docker logs <container_id> --until YYYY-MM-DD
docker logs --since <YYYY-MM-DDTHH:MM:SS> --until <YYYY-MM-DDTHH:MM:SS> <container_name_or_id>
docker logs <container_id> | grep pattern
docker logs <container_id> | grep -i error
π§ͺ LAB Activity
# Create containers to monitor log
docker run --name log -d busybox sh -c "while true; do echo \$(date) '==> Welcome to DevOps in Action!'; sleep 1; done"
docker run -d --name=grafana -p 3000:3000 grafana/grafana
docker run -d --name=logger chentex/random-logger:latest 100 400
# Set container name
container_name_or_id=logger
# Check logs with all poissble way
docker ps --size
docker logs --follow $container_name_or_id
docker logs --details $container_name_or_id
docker logs --timestamps $container_name_or_id
docker logs --tail 10 $container_name_or_id
docker logs --tail 5 --follow $container_name_or_id
docker logs $container_name_or_id --since 2025-06-10
docker logs $container_name_or_id --until 2025-06-11
docker logs --since 2025-06-10 --until 2025-06-11 $container_name_or_id
docker logs $container_name_or_id | grep -i error
docker logs $container_name_or_id | grep -i failed
docker logs $container_name_or_id | grep -i -E 'error|warning|stop|fail'
docker logs --since 2025-06-10 $container_name_or_id | grep "error"
# Stdout and Stderr log export
docker run --name log-test --rm -d busybox sh -c "echo 'This is stdout'; echo 'This is stderr' >&2; sleep 100"
docker logs log-test > /tmp/stdout.log 2>/tmp/stderr.log
cat /tmp/stdout.log
cat /tmp/stderr.log
# Check log path
docker inspect --format='{{.LogPath}}' $container_name_or_id
# View logs for a container
sudo cat /var/lib/docker/containers/<CONTAINER ID>/<CONTAINER ID>-json.log
# Tail logs for a container
sudo tail -f /var/lib/docker/containers/<CONTAINER ID>/<CONTAINER ID>-json.log
# Check size of log file of selected containers
sudo du -sh $(docker inspect --format='{{.LogPath}}' $container_name_or_id)
# Check log size of all containers at once
sudo find /var/lib/docker/containers -type f -name "*.log" -print0 | sudo du -shc --files0-from - | tail -n1
# Check log size of all containers at seprately
docker ps -aq | while read cid; do
name=$(docker inspect --format='{{.Name}}' "$cid" | sed 's/^\/\?//')
log_path=$(docker inspect --format='{{.LogPath}}' "$cid")
size=$(sudo du -sh "$log_path" 2>/dev/null | cut -f1)
echo -e "$name\t$size"
done
# Export/Backup logs way
docker logs --since=1h $container_name_or_id > /tmp/save.txt
docker logs --since="2024-12-01T00:00:00" --until="2024-12-10T23:59:59" my-container > /tmp/exported.log
sudo cp -a $(docker inspect --format='{{.LogPath}}' $container_name_or_id) /tmp/api.log
# To delete the single container logs:
# Clear log file
sudo truncate -s 0 $(docker inspect --format='{{.LogPath}}' $container_name_or_id)
#sudo echo "" > $(sudo docker inspect --format='{{.LogPath}}' $container_name_or_id)
#: > $(sudo docker inspect --format='{{.LogPath}}' $container_name_or_id)
# Delete the log files of all docker containers in your system.
sudo find /var/lib/docker/containers -type f -name "*json.log" -exec truncate -s 0 {} \;
#sudo find /var/lib/docker/containers/ -name '*-json.log' -exec truncate -s 0 {} \;
#find /var/lib/docker/containers/ -type f -name "*.log" -delete
#sudo truncate -s 0 /var/lib/docker/containers/*/*-json.log
π³ Docker Logging Lab: Inspecting Container Logs with container name, image name and id in logs π
Explore how to configure Docker logging options and inspect container logs directly from the file system with tag in log. This hands-on lab demonstrates tagging logs with metadata and analyzing structured JSON log output.
# Set container Name in logs
docker run -itd --name=nginx -p 8090:80 --log-opt tag="{{.Name}}" nginx
curl http://localhost:8090
docker logs nginx
CONTAINER_ID=$(docker inspect -f '{{.Id}}' nginx)
sudo cat /var/lib/docker/containers/$CONTAINER_ID/$CONTAINER_ID-json.log | jq
# Set container ImageName, Name and ID in logs
docker rm -f nginx
docker run -itd --name=nginx -p 8081:80 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx
curl http://localhost:8081
docker logs nginx
CONTAINER_ID=$(docker inspect -f '{{.Id}}' nginx)
sudo cat /var/lib/docker/containers/$CONTAINER_ID/$CONTAINER_ID-json.log | jq
# Alternative use below command
sudo cat /var/lib/docker/containers/$(docker inspect --format='{{.Id}}' nginx)/$(docker inspect --format='{{.Id}}' nginx)-json.log | jq
sudo jq . /var/lib/docker/containers/$(docker inspect -f '{{.Id}}' nginx)/$(docker inspect -f '{{.Id}}' nginx)-json.log
πDefault Logging Driver: json-file
The json-file
driver stores logs as JSON objects on the host filesystem, typically in /var/lib/docker/containers/<container_id>/<container_id>-json.log
. Pros:
Simple to use.
Logs are persistent on the host.
Supports
docker logs
command. Cons:Logs can consume significant disk space.
Not ideal for large-scale production.
βοΈ Setting/Changing Logging Drivers Globally π
# Check global logging driver
docker info --format '{{json .}}' | jq
docker info --format '{{.LoggingDriver}}'
# Supported plugins
docker info --format '{{json .Plugins.Log}}'
docker info --format '{{json .Plugins}}' | jq '{Log: .Log}'
Edit /etc/docker/daemon.json
to set a default logging driver for all containers:
sudo nano /etc/docker/daemon.json
# -----------------------
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
# -----------------------
## Run syslog server
docker run -d --name syslog-server \
-p 514:514/tcp -p 514:514/udp \
rsyslog/syslog_appliance_alpine
#### check logs
docker exec -it syslog-server cat /var/log/syslog
# -----------------------
{
"log-driver": "syslog",
"log-opts": {
"syslog-address": "udp://localhost:514"
}
}
# -----------------------
{
"log-driver": "syslog",
"log-opts": {
"mode": "non-blocking"
}
}
# -----------------------
{
"log-driver": "json-file",
"log-opts": {
"max-size": "25m",
"max-file": "10",
"labels": "production_bind",
"env": "os,customer"
}
}
dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker
sudo systemctl status docker
max-size
: Limits the size of each log file.max-file
: Specifies the number of rotated log files.
[!info] Ref: Daemon configuration file
π¦ Set directly log drivers to specific containers to override global config
# Run nginx override global config
docker run -d \
--name nginx \
--log-driver json-file \
--log-opt max-size=100m \
--log-opt max-file=3 \
nginx
# Check Container logging driver
docker inspect -f '{{.HostConfig.LogConfig.Type}}' nginx
β This keeps logs limited to 100MB in total (3 files Γ 100MB each).
π³ Docker Logging Drivers Overview: Customizing Logging Drivers
Docker supports multiple logging drivers to handle container logs differently based on your needs. These drivers redirect logs to various destinations such as syslog, AWS CloudWatch, or Fluentd.
π Supported Logging Drivers
Driver | Description |
π« none | No logs are available for the container and docker logs returns no output. |
π¦ local | Logs are stored in a custom format designed for minimal overhead. |
ποΈ json-file | Logs are formatted as JSON. This is the default logging driver for Docker. |
π§ syslog | Writes log messages to the syslog facility. Requires syslog daemon running on host. |
π journald | Writes log messages to journald. Requires journald daemon running on host. |
π gelf | Sends logs to a Graylog Extended Log Format (GELF) endpoint like Graylog or Logstash. |
π³ fluentd | Sends logs to Fluentd (forward input). Requires Fluentd daemon running on host. |
βοΈ awslogs | Sends logs to Amazon CloudWatch Logs. |
π splunk | Sends logs to Splunk using the HTTP Event Collector. |
πͺ etwlogs | Sends logs as Event Tracing for Windows (ETW) events. Available only on Windows platforms. |
π gcplogs | Sends logs to Google Cloud Platform (GCP) Logging. |
For each driver, you can find configurable options in the official Docker logging documentation.
β οΈ Limitations of Logging Drivers
Reading log information may require decompressing rotated log files, causing:
Temporary increase in disk usage (until logs are read)
Increased CPU usage while decompressing
The maximum size of log files depends on the capacity of the host storage where the Docker data directory resides.
π Set driver at runtime:
none
: Disables logging entirely (useful for minimal setups). docker run --log-driver=none --name my-app nginxlocal
: Stores logs in a custom binary format, optimized for performance. docker run --log-driver=local --log-opt max-size=10m --name my-app nginxsyslog
: Sends logs to a syslog server (useful for centralized logging). docker run --log-driver=syslog --log-opt syslog-address=udp://localhost:514 --name my-app nginxjournald
: Integrates withsystemd
journal for Linux systems. docker run --log-driver=journald --name my-app nginx
π GUI Logging APP 1
docker run --name dozzle -d --volume=/var/run/docker.sock:/var/run/docker.sock -p 8080:8080 amir20/dozzle:latest
# Dozzle will be available at http://localhost:8080/.
# https://github.com/amir20/dozzle
π GUI Logging APP 2
docker run --restart=always --name c-docker-web-ui -d -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock pottava/docker-webui
# Dozzle will be available at http://localhost:9000/.
# https://github.com/pottava/docker-webui
π GUI Logging APP 3
docker run -d \
-p 9000:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
portainer/portainer-ce:latest
π How to Properly Log (Best Practices)
Log to the Standard Output Stream
Limit the log size
Rotate Logs
π― Summary
Concept | Dev Environment | Production Guidance |
Default Driver | json-file | Use fluentd , gelf , etc. |
Log Rotation | Optional | Mandatory |
Centralized Logging | Optional | Highly Recommended |
Log Structure | Text logs | Structured JSON logs |
Log Forwarding | Not needed | Critical for monitoring/alert |
π³ Docker Logging Resources
π·οΈ Log Tags Overview
Learn about available log tags and how to use them with logging drivers.βοΈ Daemon Configuration File
Configure the Docker daemon using a JSON file, including logging settings.π Container Logs Command
Usage guide for thedocker container logs
CLI command.π οΈ Configure Logging Drivers
Instructions on how to configure different logging drivers in Docker.π Log Tags in Container Logging
Additional info on log tags for container logging configuration.
Subscribe to my newsletter
Read articles from Ibrar Ansari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Ibrar Ansari
Ibrar Ansari
Hello! I'm a DevOps Engineer dedicated to continuous learning and contributing to the tech community. If you find value in what I share, feel free to spread the word to others who might benefit as well. Your support is greatly appreciated!