Docker Swarm mode setup with Docker Machine
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, 0.0.0.0:8000->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
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 \ swarm-manager-01
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN \ --swarm \ --swarm-discovery token://swarm-is-all-we-need \ swarm-node-01
docker-machine create --driver digitalocean --digitalocean-access-token=DO-ACCESS-TOKEN \ --swarm \ --swarm-discovery token://swarm-is-all-we-need \ swarm-node-02
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:
ID NAME REPLICAS IMAGE COMMAND 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.