Docker and Swarmkit – Part 6 – New Features of v1.13

In a few days version 1.13 of Docker will be released and among other it contains a lot of new features for the Docker Swarmkit. In this post I want to explore some of these new capabilities.

In the last few parts of this series of posts about the Docker Swarmkit we have used version 1.12.x of Docker. You can find those post here

Part 1, Part 2, Part 3, Part 4 and Part 5

For a full index of all Docker related post please refer to this post

Preparating for Version 1.13

First we need to prepare our system to use Docker 1.13. I will be using VirtualBox and the Boot2Docker ISO to demonstrate the new features. This is what I have done to get going. Note that at the time of this writing Docker just released Docker v1.13 rc2.

First I am going to install the newest version of docker-machine on my Mac. The binaries can be downloaded from here. In my case the package I download is docker-machine-Darwin-x86_64 v0.9.0-rc1

From the download folder move the binaries to the target folder

mv ~/Downloads/docker-machine-Darwin-x86_64 /usr/local/bin/docker-machine

and then make it executable

chmod +x /usr/local/bin/docker-machine

finally we can double check that we have the expected version

docker-machine -v

and in my case I see this

docker-machine version 0.9.0-rc1, build ed849a7

Now let’s download the newest boot2docker.iso image. At the time of this writing it is v1.13rc2. We can get it from here. Once downloaded move the image to the correct location

mv ~/Downloads/boot2docker.iso ~/.docker/machine/cache/

And we’re ready to go…

Creating a Docker Swarm

Preparing the Nodes

Now we can create a new swarm with Docker at version 1.13. We use the very same approach as described in part x of this series. Please read that post for more details.

Let’s clean up any pre-existing nodes called node1, node2, …, noneX with e.g. the following command

for n in $(seq 1 5); do
  docker-machine rm node$n
done;

and then we create 5 new nodes with Docker version 1.13rc2

for n in $(seq 1 5); do
  docker-machine create --driver virtualbox node$n
done;

Once this is done (takes about 2 minutes or so) we can double check the result

docker-machine ls

which in my case shows this

Now we can SSH into node1

docker-machine ssh node1

and we should see this

and indeed, we are now having a Docker host running at version 1.13.0-rc2.

Creating the Swarm

Now lets first initialize a swarm. node1 will be the leader and node2 and node3 will be additional master nodes whilst node4 and node5 will be worker nodes (Make sure you are in a terminal on your Mac).

First let’s get the IP address of the future swarm leader

export leader_ip=`docker-machine ip node1`

Then we can initialize the swarm

docker-machine ssh node1 docker swarm init --advertise-addr $leader_ip

Now let’s get the swarm join token for a worker node

export token=`docker-machine ssh node1 docker swarm join-token worker -q`

We can now use this token to have the other 4 nodes join as worker nodes

for n in $(seq 2 5); do
  docker-machine ssh node$n docker swarm join --token $token $leader_ip:2377
done;

what we should see is this

Let’s promote nodes 2 and 3 to masters

docker-machine ssh node1 docker node promote node2 node3

And to make sure everything is as expected we can list all nodes on the leader

docker-machine ssh node1 node ls

In my case I see this

Adding everything to one script

We can now aggregate all snippets into one single script which makes it really easy in the future to create a swarm from scratch

# --------------------------------------------------------------
# script to create a new Docker Swarm from scratch on VirtualBox
# --------------------------------------------------------------
#!/usr/bin/bash

NUM_NODES=5
LEADER_NODE=node-1

# clean up
for NODE in $(seq 1 $NUM_NODES); do
  echo 'y' | docker-machine rm node-$NODE
done;

# create nodes
for NODE in $(seq 1 $NUM_NODES); do
  docker-machine create --driver virtualbox node-$NODE
done;

LEADER_IP=`docker-machine ip $LEADER_NODE`

# initialize swarm
docker-machine ssh $LEADER_NODE docker swarm init --advertise-addr $LEADER_IP

# Now let's get the swarm join token for a worker node
JOIN_TOKEN=`docker-machine ssh $LEADER_NODE docker swarm join-token worker -q`

# all other nodes join as workers
for n in $(seq 2 $NUM_NODES); do
  docker-machine ssh node-$n docker swarm join --token $JOIN_TOKEN $LEADER_IP:2377
done;

# promote node 2 and 3 to master role
docker-machine ssh $LEADER_NODE docker node promote node-2 node-3

# finally show all nodes
docker-machine ssh $LEADER_NODE docker node ls

Analyzing the new Features

Secrets

One of the probably most requested features is support for secrets managed by the swarm. Docker supports a new command secret for this. We can create, remove, inspect and list secrets in the swarm. Let’s try to create a new secret

echo '1admin2' | docker secret create 'MYSQL_PASSWORD'

The value/content of a secret is provided via stdin. In this case we pipe it into the command.

When we run a service we can map secrets into the container using the --secret flag. Each secret is mapped as a file into the container at /run/secrets. Thus, if we run a service like this

docker service create --name mysql --secret MYSQL_PASSWORD \
      mysql:latest ls /run/secrets

and then observe the logs of the service (details on how to use logs see below)

docker service logs mysql

we should see this

The content of each file corresponds to the value of the secret.

Publish a Port

When creating an new service and want to publish a port we can now instead of only using the somewhat condensed --publish flag use the new --port flag which uses a more descriptive syntax (also called ‘csv’ syntax)

docker service create --name nginx --port mode=ingress,target=80,published=8080,protocol=tcp nginx

In my opinion, altough the syntax is more verbous it makes things less confusing. Often people with the old syntax forgot in which order the target and the published port have to be declard. Now it is evident without having to consult the documentation each time.

Attachable Network support

Previously it was not possible for containers that were run in classical mode (via docker run ...) to run on the same network as a service. With version 1.13 Docker has introduced the flag --attachable to the network create command. This will allow us to run services and individual containers on the same network. Let’s try that and create such a network called web

docker network create --attachable --driver overlay web

and let’s run Nginx on as a service on this network

docker service create --name nginx --network web nginx:latest

and then we run a conventional container on this network that tries to acces the Nginx service. First we run it without attaching it to the web network

docker run --rm -it appropriate/curl nginx

and the result is as expected, a failure

And now let’s try the same again but this time we attach the container to the web network

docker run --rm -it --network web appropriate/curl nginx:8080

Run Docker Deamon in experimental mode

In version 1.13 the experimental features are now part of the standard binaries and can be enabled by running the Deamon with the --experimental flag. Let’s do just this. First we need to change the dockerd profile and add the flag

docker-machine ssh node-1 -t sudo vi /var/lib/boot2docker/profile

add the --experimental flag to the EXTRA_ARGS variable. In my case the file looks like this after the modification

EXTRA_ARGS='
--label provider=virtualbox
--experimental

'
CACERT=/var/lib/boot2docker/ca.pem
DOCKER_HOST='-H tcp://0.0.0.0:2376'
DOCKER_STORAGE=aufs
DOCKER_TLS=auto
SERVERKEY=/var/lib/boot2docker/server-key.pem
SERVERCERT=/var/lib/boot2docker/server.pem

Save the changes as reboot the leader node

docker-machine stop node-1
docker-machine start node-1

After the node is ready SSH into it

docker-machine ssh node-1

Aggregated logs of a service (experimental!)

In this release we can now easily get the aggregated logs of all tasks of a given service in a swarm. That is neat. Lets quickly try that. First we need to run Docker in experimental mode on the node where we execute all commands. Just follow the steps in the previous section.

Now lets create a sample service and run 3 instances (tasks) of it. We will be using Redis in this particular case, but any other service should work.

docker service create --name Redis --replicas 3 redis:latest

after giving the service some time to initialize and run the tasks we can now output the aggregated log

docker service logs redis

and we should see something like this (I am just showing the first few lines)

redis.2.lrtyxhq2q1xm@node-3    | 1:C 25 Nov 18:27:51.687 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis.2.lrtyxhq2q1xm@node-3    |                 _._
redis.2.lrtyxhq2q1xm@node-3    |            _.-``__ ''-._
redis.2.lrtyxhq2q1xm@node-3    |       _.-``    `.  `_.  ''-._           Redis 3.2.5 (00000000/0) 64 bit
redis.2.lrtyxhq2q1xm@node-3    |   .-`` .-```.  ```\/    _.,_ ''-._
redis.2.lrtyxhq2q1xm@node-3    |  (    '      ,       .-`  | `,    )     Running in standalone mode
redis.2.lrtyxhq2q1xm@node-3    |  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
redis.2.lrtyxhq2q1xm@node-3    |  |    `-._   `._    /     _.-'    |     PID: 1
redis.2.lrtyxhq2q1xm@node-3    |   `-._    `-._  `-./  _.-'    _.-'
redis.2.lrtyxhq2q1xm@node-3    |  |`-._`-._    `-.__.-'    _.-'_.-'|
redis.2.lrtyxhq2q1xm@node-3    |  |    `-._`-._        _.-'_.-'    |           http://redis.io
redis.2.lrtyxhq2q1xm@node-3    |   `-._    `-._`-.__.-'_.-'    _.-'
redis.3.zls0kbe6qqwm@node-4    | 1:C 25 Nov 18:27:53.387 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis.3.zls0kbe6qqwm@node-4    |                 _._
redis.3.zls0kbe6qqwm@node-4    |            _.-``__ ''-._
redis.2.lrtyxhq2q1xm@node-3    |  |`-._`-._    `-.__.-'    _.-'_.-'|
redis.2.lrtyxhq2q1xm@node-3    |  |    `-._`-._        _.-'_.-'    |
redis.2.lrtyxhq2q1xm@node-3    |   `-._    `-._`-.__.-'_.-'    _.-'
redis.1.ml5e93kvr59p@node-5    | 1:C 25 Nov 18:27:53.044 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis.1.ml5e93kvr59p@node-5    |                 _._
redis.1.ml5e93kvr59p@node-5    |            _.-``__ ''-._
redis.1.ml5e93kvr59p@node-5    |       _.-``    `.  `_.  ''-._           Redis 3.2.5 (00000000/0) 64 bit
redis.1.ml5e93kvr59p@node-5    |   .-`` .-```.  ```\/    _.,_ ''-._
redis.1.ml5e93kvr59p@node-5    |  (    '      ,       .-`  | `,    )     Running in standalone mode
redis.1.ml5e93kvr59p@node-5    |  |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
redis.1.ml5e93kvr59p@node-5    |  |    `-._   `._    /     _.-'    |     PID: 1
redis.1.ml5e93kvr59p@node-5    |   `-._    `-._  `-./  _.-'    _.-'
redis.1.ml5e93kvr59p@node-5    |  |`-._`-._    `-.__.-'    _.-'_.-'|
redis.1.ml5e93kvr59p@node-5    |  |    `-._`-._        _.-'_.-'    |           http://redis.io
redis.1.ml5e93kvr59p@node-5    |   `-._    `-._`-.__.-'_.-'    _.-'
redis.1.ml5e93kvr59p@node-5    |  |`-._`-._    `-.__.-'    _.-'_.-'|
redis.1.ml5e93kvr59p@node-5    |  |    `-._`-._        _.-'_.-'    |
redis.1.ml5e93kvr59p@node-5    |   `-._    `-._`-.__.-'_.-'    _.-'
redis.1.ml5e93kvr59p@node-5    |       `-._    `-.__.-'    _.-'
redis.1.ml5e93kvr59p@node-5    |           `-._        _.-'
redis.1.ml5e93kvr59p@node-5    |               `-.__.-'
redis.1.ml5e93kvr59p@node-5    |
redis.1.ml5e93kvr59p@node-5    | 1:M 25 Nov 18:27:53.045 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.

We can clearly see how the output is aggregated from the 3 tasks running on nodes 3, 4 and 5. This is a huge improvement IMHO and I can’t wait until it is part of the stable release.

Summary

In this post we have created a Docker swarm on VirtualBox using the new version 1.13.0-rc2 of Docker. This new release offers many new and exciting features. In this post I have concentrated on some of the features concerning the Swarmkit. My post is getting too long and I have still so many interesting new features to explore. I will do that in my next post. Stay tuned.

About Gabriel Schenker

Gabriel N. Schenker started his career as a physicist. Following his passion and interest in stars and the universe he chose to write his Ph.D. thesis in astrophysics. Soon after this he dedicated all his time to his second passion, writing and architecting software. Gabriel has since been working for over 25 years as a consultant, software architect, trainer, and mentor mainly on the .NET platform. He is currently working as senior software architect at Alien Vault in Austin, Texas. Gabriel is passionate about software development and tries to make the life of developers easier by providing guidelines and frameworks to reduce friction in the software development process. Gabriel is married and father of four children and during his spare time likes hiking in the mountains, cooking and reading.
This entry was posted in containers, docker, How To, introduction and tagged , , . Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Guillaume

    Hello Gabriel,
    Thanks for this great article ! I would like to install v1.13rc2 with Docker-Machine but with another driver than virtualbox (google for example) : is it possible ?
    I saw that the option “–engine-install-url” allows to specify an installation script for Docker Engine but I did not find a script to install the 1.13-rc2 (I tried the script mentionned the Download section of the release page https://github.com/docker/docker/releases but it points to “https://test.docker.com/” and that installed a v1.12 version…
    Do you know a way to do this please ?