Hi, I'm Daisy

Here is a place for my random musings!

Exploring Docker Logs

The mechanics of Docker logs are, by nature, quite different from VM logs and managing Docker logs can be complicated due to its dynamic and ephemeral nature. In the Docker universe, there are different types of logs to be mindful of: logs from the containerized applications and logs from the Docker daemon. In order to gain insight into the health of your containers, you need to understand the structure of Docker logs and what it tells you. It can give you a full picture of what is happening at every layer of the stack. Once all the logs have been collected and we have access to them, how do we make use of them and interpret the results? This post aims to give an overview of Docker logs, it’s structure, and what exactly it tells us.

Basics

Docker logs are the console output of running containers. We get the stdout and stderr streams of processes running in a container. Most official Docker images log to console.

Anything written by a container on stdout and stderr is collected by the docker engine and sent to the logging driver. This may contain startup messages if something is not correctly configured and access-log typed messages that are structured with IP addresses, timestamps, and status code.

To view a container’s logs, identify the container ID or the image name and then type:

docker logs [OPTIONS] CONTAINER

An example output:

172.17.0.1 - - [26/Dec/2017:07:25:23 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/63.0.3239.84 Chrome/63.0.3239.84 Safari/537.36" "-"
2017/12/26 07:25:23 [error] 7#7: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "172.17.0.2", referrer: "http://172.17.0.2/"

If the default logging driver is used, Docker logs can be found under:

/var/lib/docker/containers/<container id>/<container id>-json.log

To find the specific location of Docker logs, type: docker inspect CONTAINER | grep LogPath

An example output:

"LogPath": "/var/lib/docker/containers/61967306d3ee8855ec7ee45ae6cc4ec08ebf7e61fcacedfc096740bdc637ed92/61967306d3ee8855ec7ee45ae6cc4ec08ebf7e61fcacedfc096740bdc637ed92-json.log"	

Logging drivers

The Docker engine provides various logging drivers that determine where logs are sent or written to. The default driver for Docker logs is “json-file”, which writes the logs to local files on the Docker host in json format, and allows them to be viewed on the console with the CLI tool. If the default driver is used, the logs are removed upon removal of the container. There are other logging drivers that allow Docker logs to be sent via the driver (without parsing) to a remote destination. Some examples are syslog, gelf, fluentd, journald. A log driver can be set up for each container, which specifies where logs should go for that particular container. A global daemon-wide setting for Docker can also be created.

To set a logging driver for a container, this would be done with the --log-driver option:

docker run --log-driver=DRIVERNAME

To set extra options, use --log-opt. For example, when using the syslog driver, the address of the remote syslog server can be set:

docker run --log-driver=syslog --log-opt=syslog-address=ADDRESS

When one of these drivers is in use, the Docker logs are shipped via the driver to a remote destination and the logs are not on the local Docker host. Thus, the CLI tool to display logs will not work anymore since Docker does not know how to retrieve the logs from these systems.

For example, the syslog protocol only defines how to send logs to a remote logger, but not how to access them. With other drivers, once the logs are sent to a particular logging system, they are outside of Docker’s reach.

Structure of Docker container logs and its contents

Anything written by a container on stdout and stderr is collected by the Docker engine and sent to the logging driver. The logs contain the actual message output plus a bunch of metadata (which becomes very important at large scale)

Each line of the log consists of a timestamp (with date, full year, and down to milliseconds), a string, and perhaps an origin (stdout vs stderr).

An example output:

172.17.0.1 - - [24/Apr/2018:07:25:23 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/63.0.3239.84 Chrome/63.0.3239.84 Safari/537.36" "-"
2018/04/24 07:25:23 [error] 7#7: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "172.17.0.2", referrer: "http://172.17.0.2/"

Another example output:

2018-04-24T06:40:35.359+0000 I CONTROL  [initandlisten] MongoDB starting : port=27017 dbpath=/data/db 64-bit
 2018-04-24T06:40:35.359+0000 I CONTROL  [initandlisten] db version v3.6.3

 2018-04-24T06:40:35.360+0000 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine

The log output may be different depending on what logging driver is in use. For example, priority (i.e. debug, warning, error, info) and the PID (process name or process ID) are informations that exist for syslog, but not for container output. If you use an advanced logging driver like gelf, a lot of container information will be added and every log message is a dict.

The --details flag will add on extra attributes, such as environment variables and labels, provided to --log-opt when creating the container.

An example:

docker run -d --log-opt tag=hi=what,day=wednesday alpine echo hello world

c93bf3bcedc9a87082123bbd0d17f21d7e876f8c593da129277e931b8890a4d0

docker logs c93b

hello world

docker logs c93b --details

tag=hi%3Dwhat%2Cday%3Dwednesday hello world

Docker daemon logs

Docker daemon logs offers insight into the state of the Docker service as a whole. It logs two types of events: commands sent to the daemon through Docker’s Remote API and events that occur as part of the daemon’s normal operation.

Viewing Docker daemon logs is quite different from viewing logs from the containerized applications. It depends on your operating system.