What’s New in Docker 1.12 – Part 1

Docker 1.12 adds quite a few new features, the biggest of those being the new Swarm Mode that was announced at DockerCon 2016. However, the release notes includes a long list of other changes, some of which may have been lost in the excitement over Swarm. In this first part, we are taking a deeper dive into the changes introduced to building images, distribution, and logging.

Building Images

The release notes begins with building images using Dockerfiles and one small change to .dockerignore. The first of these changes to the Dockerfile is second only to the Swarm updates in terms of it’s popularity, healthcheck!

Healthcheck

The healthcheck is a user configurable entry in the Dockerfile that tells Docker how to monitor your container. Before this, the most Docker would say is whether the process was still up. Now you can define your own command that gets run inside of your container which Docker will use to monitor your container’s health. The new Dockerfile entry has the following syntax:

HEALTHCHECK CMD

Possible options include:

--interval=DURATION (default: 30s)

--timeout=DURATION (default: 30s)

--retries=N (default: 1)

Docker looks at the exit value of the cmd to determine the state:

0: success – the container is healthy and ready for use

1: unhealthy – the container is not working correctly

2: starting – the container is not ready for use yet

Only one healthcheck is available per image, with the last definition overwriting all previous definitions, identical to the behavior of entries like CMD and ENTRYPOINT. To disable the healthcheck (e.g. from an upstream image you included in your FROM) you use:

HEALTHCHECK none

A failing healthcheck:

Generates an event

Shows in docker ps

Does not restart container when unhealthy outside of Swarm

Does not delay startup of dependent containers with Compose

Swarm containers will be stopped and replaced with healthy instances

With Swarm mode, a container also avoids being ready on startup until this check succeeds. One important note is that the command provided will bypass the SHELL, CMD, and ENTRYPOINT.

The application itself simply listens on port 80 for requests to change the “/status” link from healthy to failed with a 500 HTTP status. The important thing to note from the above Dockerfile is the install of curl for the healthcheck since this check runs inside of your container. We then launch the container and monitor the status with the following commands:

In addition to monitoring the status in docker ps, the inspect output shows the current healthcheck state along with the results of the past runs. Those results include a timestamp, output, and exit code to make debugging easier.

Healthcheck with Swarm

To take full advantage of the healthcheck, you need a tool listening for the events and recovering from the failures. Docker provides this out of the box as part of their Swarm mode offering. Here’s a similar scenario run with 3 replicas in Swarm:

Shell

Docker introduced a new SHELL command for Dockerfiles. This can be used to modify the shell used in RUN, CMD, and ENTRYPOINT when they are defined as strings. When these values are defined as JSON arrays, they have always bypassed the shell and will continue to do so. If you define the SHELL multiple times, the last value is used. This value is inherited from parent images.

The main use case for this will be Windows images where they are looking at the ability to swap between cmd and powershell with the following entries:

Escape

Another change being added in preparation for Windows images is the ability to change the escape character from \ to `. The backslashes, while well known as an escape in Linux, are unfortunately path separators in Windows. This directive, unlike other Dockerfile commands, is defined as a comment at the top of the Dockerfile in the format # escape=`. It only applies to the current Dockerfile, not to any child images that are built off of the resulting image. This prevents an upstream change from breaking your Dockerfiles.

Note that only the two preselected escape characters are currently allowed, \ and `. This was done to avoid Dockerfiles that changed the escape to unexpected characters like a space.

Comments in .dockerignore

Docker added the ability to include comments inside of .dockerignore files. These use the # prefix and are only supported at the beginning of the line. If you include a # on the same line as a filename, it is interpreted as part of the filename and the file is no longer ignored. Here’s an example of what a .dockerignore file would look like:

# Sample comment
.git
passwords # this file is still included

Other Build Changes

One other change in the build section is the ability to build images without a bridged network configured in the docker engine. This is a pretty unique use case that most users won’t encounter. Pull request #22932 has more details.

Distribution

There were only a few changes to distribution in this release, focusing on incremental changes to push, pull, save, and load.

Concurrent Downloads

Docker now allows you to configure the number of concurrent downloads and uploads for push and pull operations. The defaults of 3 downloads and 5 uploads remain the same. This change is made on the Docker daemon and affects all pull and pull operations on that host. If you’re on a restricted network that doesn’t allow more than one connection out per destination concurrently, adjusting these settings to 1 each may resolve issues. Conversely, if you are on a large server and fast network with lots of images to move, increasing these values may improve your throughput.

To adjust these settings you’ll need to modify your engine’s startup scripts with the following flags:

$ dockerd --help
# ...
--max-concurrent-downloads=3 Set the max concurrent downloads for each pull
--max-concurrent-uploads=5 Set the max concurrent uploads for each push
# ...

Show Image Name or ID on Load

This next one is small but can help with debugging scripts that move lots of images from the docker save and docker load CLI. Now after loading an image, the client will output the image name (tag) or if it’s untagged, it will show the image id. Before, load wouldn’t output anything unless there was an error, so if you loaded multiple images, you may not know which threw the error.

Logging

Log Labels

Docker extended --log-opt to allow “labels” to be included in the output. This will be useful for log aggregation tools that gather logs from multiple containers and need to filter the results. You pass the name of the label to include with --log-opt labels= where list can be a comma separate list. The labels themselves can be assigned to the individual containers with --label =. The labels will only be shown in the output of docker logs if you include the --details option. Putting that all together looks like:

Microsecond Support in Syslog Driver

The syslog logging driver has a new output format “rfc5424micro” that includes microseconds in the timestamps. This timestamp is otherwise identical to the rfc5424 format that was already available. This will be useful if you’re using logs to debug performance problems. Here’s an example of using this new format: