Docker Swarm Local Environment

Docker Swarm Vagrant

The Vagrantfile can be used to spin few nodes with Docker Swarm and Docker API configured. The boxes are running Ubuntu 16.04(Xenial) amd64.

Requirements

Vagrant and VirtualBox need to be installed on your workstation.

Customize

By default vagrant up spins up 3 machines: manager, worker1, worker2. You can adjust how many workers you want in the Vagrantfile, by setting the numworkers variable. Manager, by default, has address "192.168.10.2", workers have consecutive ips.

numworkers = 2

If your provisioner is Virtualbox, you can modify the vm allocations for memory and cpu by changing these variables:

vmmemory = 512
numcpu = 1

/etc/hosts on every machine is populated with an IP address and a name of every other machine, so that names are resolved within the cluster. This mechanism is not idempotent, reprovisioning will append the hosts again.

Auto mode

By default, vagrant will create a docker swarm cluster. You can run AUTO_START_SWARM=false vagrant up to provision individual docker hosts

Configure Docker Swarm Manually

Go to the master node and start docker swarm:

   (host)# vagrant ssh manager
(manager)# docker swarm init --advertise-addr 192.168.10.2

docker swarm join \
--token SWMTKN-1-59h28hcbb8gzs2xs24oyh7hjvc7fp8skjzvnpw9cksmp96m4y2-35er9ai3u1f1ae5esb7x8l1hx \
192.168.10.2:2377

Basic Usage

After starting swarm, you can use my testing Docker image to play with. It is called darek/goweb and is a super simple Web app, displaying the hostname, and a version. They can be used to play with swarm rolling update feature. The container exposes port 8080.

Now join the swarm on the nodes with the command from the manager, do it on both nodes. You can verify that nodes are in the cluster by doing docker nodes ls on the manager.

vagrant@manager:~$ docker node ls
ID                           HOSTNAME  STATUS  AVAILABILITY  MANAGER STATUS
0rtuyz07e0wazmxvoed1llmx3 *  manager   Ready   Active        Leader
1iab1w9m5znyzmh7hpzyn7rrw    worker2   Ready   Active
4mmca5rxrxxhb0tb7s5du5hpe    worker1   Ready   Active

Now create a web service, with 1 replica, on any of the nodes:

docker service create --name web --replicas 3 --publish 8080:8080 darek/goweb:1.0

You can see the status od the service with docker service ps web.

vagrant@manager:~$ docker service  ps web
ID                         NAME   IMAGE            NODE     DESIRED STATE  CURRENT STATE           ERROR
7m0s3ikyjyvps4xgpk655uv9k  web.1  darek/goweb:1.0  manager  Running        Running 16 seconds ago

You can scale up the service if you want:

docker service scale web=6

Now, let us verify it works, docker swarm will load balance requests to all of the service instances:

vagrant ssh worker1
sudo apt-get install httpie -y
http localhost:8080

Do the http command serveral times, you will notice different hostnames every time. This is because swarm handler load balancing for us.

Let's do a rolling update of the service, first let's scale it to 10 - you already know how. First we will update the defintion of the service to say that updates will have a delay of 5s.

docker service update --update-delay 5s web

Let's us update the service now:

docker service update --image darek/goweb:2.0 web

Now docker will update service one by one with a 5s delay between the updates. If you want to introduce parallelism to updates you can specify if with the --update-parallelism flag.

docker service update --update-parallelism 2 web

Let's see how it goes:

vagrant@manager:~$ docker service ps web
ID                         NAME        IMAGE            NODE     DESIRED STATE  CURRENT STATE                    ERROR
7m0s3ikyjyvps4xgpk655uv9k  web.1       darek/goweb:1.0  manager  Running        Running 8 minutes ago
f49k99apn8yzve0uh8zsyigw6  web.2       darek/goweb:1.0  worker1  Running        Running 7 minutes ago
8t9x9qqqxztzd8msuccbx43mg  web.3       darek/goweb:2.0  manager  Running        Running 11 seconds ago
38pl9czfhaztifjsb605wi2m9   \_ web.3   darek/goweb:1.0  worker1  Shutdown       Shutdown 16 seconds ago
5y4iaxmv1jhdw5b7qroessmr9  web.4       darek/goweb:1.0  worker2  Running        Running 7 minutes ago
2zhfna5m15cd482hbt06kc139  web.5       darek/goweb:2.0  worker1  Running        Preparing 1 seconds ago
3ydym0s1iq0psko60zi66ojvs   \_ web.5   darek/goweb:1.0  manager  Shutdown       Shutdown less than a second ago
9feao0z26oc75qgoktuc16pro  web.6       darek/goweb:1.0  manager  Running        Running about a minute ago
14tsult13blurmrh2klf7sm7i  web.7       darek/goweb:2.0  worker2  Running        Running 43 seconds ago
1qtcsaohat94puoym9i6zsadf   \_ web.7   darek/goweb:1.0  manager  Shutdown       Shutdown 48 seconds ago
8d2qnv19urq2yzlmqzud41ffa  web.8       darek/goweb:1.0  worker2  Running        Running about a minute ago
9shytfqyotuuyaj5hiddnymd4  web.9       darek/goweb:1.0  worker2  Running        Running about a minute ago
9kr6ehtv093cnmdxo55sy4pl9  web.10      darek/goweb:2.0  worker1  Running        Running 27 seconds ago
1yvwgb25d8fbarrabyeqha843   \_ web.10  darek/goweb:1.0  worker1  Shutdown       Shutdown 31 seconds ago

Some services are already updated. Nice.

You can also inspect the service by docker service inspect --pretty web.

vagrant@manager:~$ docker service inspect --pretty web
ID:		0iqjzgky9p7ilky60xff4ovgt
Name:		web
Mode:		Replicated
 Replicas:	10
Update status:
 State:		completed
 Started:	3 minutes ago
 Completed:	48 seconds ago
 Message:	update completed
Placement:
UpdateConfig:
 Parallelism:	1
 Delay:		10s
 On failure:	pause
ContainerSpec:
 Image:		darek/goweb:2.0
Resources:
Ports:
 Protocol = tcp
 TargetPort = 8080
 PublishedPort = 8080

After the update, you can verify that the version is really 2.0 with the httpie command. Let's now delete the service.

docker service rm web

Access Docker API

List Docker containers

curl http://192.168.10.2:4243/containers/json | jq .

Docker Info

curl http://192.168.10.2:4243/info | jq .

Kill Vagrant Boxs

Destroy the vm's with: vagrant destroy --force.


Inspired by: https://github.com/tdi/vagrant-docker-swarm