Docker Swarm mode setup with Docker Machine

Tutorial on how to use Docker Machine to setup docker 1.21 swarm

Perica Zivkovic

5minute read

Last time we took a look on how to setup local swarm with Docker 1.21. This time we will extend that a bit and see how to use Docker Machine to accomplish the same setup.

Docker Machine allows to specify where our environment will be running by using different “drivers” to provision multiple remote Docker hosts on various flavors of Linux. At the moment big set of drivers is supported, in our example we will use Digital Ocean as a host for swarm nodes. To follow the steps described here you will need a DO account and DO access token so that you can create droplets via DO API. In case you don’t have a DO account, you can use this link to subscribe and you will receive 10$ DO credit!

Let’s first go and see how to spin up a docker client on a new DO droplet with Docker Machine. Simply, by running following command:

docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN test-this

Will do following steps:

Creating CA: /home/perica/.docker/machine/certs/ca.pem
Creating client certificate: /home/perica/.docker/machine/certs/cert.pem
Running pre-create checks...
Creating machine...
(test-this) Creating SSH key...
(test-this) Creating Digital Ocean droplet...
(test-this) Waiting for IP address to be assigned to the Droplet...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env test-this

This will create a minimal DO droplet (512MB one, at the moment of this post) based on Ubuntu 16.04.1, it will configure SSH keys and certificates and install latest docker on it! How simple and powerful was that, huh? You can connect to your DO console and you will see your droplet up and running. To connect your shell to your new droplet with Docker Client, lets run eval $(docker-machine env test-this). Now every docker command in this session will be executed on your droplet.

Lets test this and create some containers on this droplet! E.g. Nginx is a nice one to try, docker run -d -p 8000:80 nginx will be done quite quickly and usual docker ps will show our container up and running:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                           NAMES
71815a959e72        nginx               "nginx -g 'daemon off"   15 seconds ago      Up 14 seconds       443/tcp,>80/tcp   thirsty_curie

I know what are you thinking now, “too easy to be true!”, well that was my thinking also so lets see does this really run on our droplet docker-machine stop test-this

Now this should stop your droplet and if the previous docker ps and container was really executed on the droplet, it should now be offline, lets check again with docker ps:

Cannot connect to the Docker daemon. Is the docker daemon running on this host?

It worked! Our DO console will also confirm that our droplet is stopped. As we will now start playing with swarm and create a new setup for that, lets remove this test Docker Machine instance with docker-machine rm test-this. You will get a simple prompt that asks are you sure, confirming that will remove your DO droplet and Docker Machine that was created.

Now lets set up a swarm cluster with Docker Machine on DO with one swarm manager and two nodes, according to the official documentation, this is as simple as:

docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN \
    --swarm \
    --swarm-master \
    --swarm-discovery token://swarm-is-all-we-need \
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN \
    --swarm \
    --swarm-discovery token://swarm-is-all-we-need \
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN \
    --swarm \
    --swarm-discovery token://swarm-is-all-we-need \

So 5 minutes later and our swarm is up and running! Lets test it, first lets connect our shell with swarm-manager:

eval "$(docker-machine env --swarm swarm-manager-01)"

If you now try to use your swarm with docker node ls you will get:

Error response from daemon: 404 page not found

Wait what? But my droplets are running, docker info is reporting containers running, where is the magic?!? Well it turns out that docker machine is still creating old version of swarm, not the docker 1.21 swarm. Ugh! This will probably be updated in new versions but in the current (at the moment of this post) Docker Machine 0.8.1, to create new type of swarm based on docker 1.21 you need to do following steps.

First delete three droplets that you just created :-) with docker-machine rm swarm-manager-01, docker-machine rm swarm-node-01 and docker-machine rm swarm-node-02.

Now lets create new nodes:

docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN swarm-manager-01
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN swarm-node-01
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN swarm-node-02

So three clean nodes with Docker Client are up and running, check, lets now configure swarm on them:

MANAGER_IP=$(docker-machine ip swarm-manager-01)
docker-machine ssh swarm-manager-01 docker swarm init --advertise-addr $MANAGER_IP

Good, so swarm manager is now up and running, lets add our nodes to the swarm:

WORKER_TOKEN=$(docker-machine ssh swarm-manager-01 docker swarm join-token --quiet worker)
docker-machine ssh swarm-node-01 docker swarm join --token $WORKER_TOKEN $MANAGER_IP:2377
docker-machine ssh swarm-node-02 docker swarm join --token $WORKER_TOKEN $MANAGER_IP:2377

So now after eval "$(docker-machine env swarm-manager-01)" if you try to see the status of your swarm with docker node ls you will get:

ID                           HOSTNAME          STATUS  AVAILABILITY  MANAGER STATUS
1j2utm4ctpczk112cgocs5px2 *  swarm-manager-01  Ready   Active        Leader
3ds7usi217rc52ofup3591371    swarm-node-02     Ready   Active
77tj6gli92iu8zqfewecanr2c    swarm-node-01     Ready   Active

Yay! It looks like it worked. How about we put some load on this swarm :-)

docker service create --name web --replicas=10 -p 30000:80 nginx

This should create nginx service on your shiny new swarm with 10 replicas, you can check that with docker service ls and you should get:

9f498fuais9q  web   10/10     nginx

Well that’s all for now, just a small reminder that you delete your Docker Machines on DO after you are done with playing with docker-machine rm [node-name] to save some $$ and make sure that they are actually stopped and deleted by checking your DO droplets page.

comments powered by Disqus