This is the second post of a two part series on ASP.NET Core, Docker, and Docker Swarm. In our previous post, we created an ASP.NET Core Docker container and pushed it to Docker Hub. Along the way, we took a look at a couple third party tools, such as Yeoman. To continue our journey, we will take the container we previously created and host it in a highly available Docker Swarm cluster.
Creating Docker Machines
Using Docker Swarm wouldn’t benefit us much without having a couple hosts. Lets get started by creating those. The Docker Toolbox comes equipped with
docker-machine for managing your local docker hosts. We can use the
create command to create our new hosts.
λ docker-machine create --driver virtualbox swarm-demo-1 λ docker-machine create --driver virtualbox swarm-demo-2 λ docker-machine create --driver virtualbox swarm-demo-3
After the commands have completed, if you open VirtualBox Manager you will see our three hosts running.
You can also run the following command to see a list of all your docker machines and their status.
λ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS swarm-demo-1 - virtualbox Running tcp://192.168.99.100:2376 v1.13.1 swarm-demo-2 - virtualbox Running tcp://192.168.99.101:2376 v1.13.1 swarm-demo-3 - virtualbox Running tcp://192.168.99.102:2376 v1.13.1
Setting up the Cluster
To create the swarm cluster, lets
ssh into the machine that we want to be the master node.
λ docker-machine ssh swarm-demo-1
Now we want to run the
swarm init command. The init command takes the –advertise-addr parameter to which we will want to supply our nodes public IP address. In my case, this is 192.168.99.100.
docker@swarm-demo-1:~$ docker swarm init --advertise-addr 192.168.99.100 Swarm initialized: current node (syer49bixi68zkw5tdebej4by) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-452450rx24myaxaac49y67qijz5e3zoa84li5vvioy2sbrorhb-3cv994lxh25419huwynze0d0u \ 192.168.99.100:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Note the results from the command. We will use the
docker swarm join command to join other nodes to the swarm cluster.
We are going to create the swarm-demo-2 node as a backup manager. To do this, we will first ssh into this node.
λ docker-machine ssh swarm-demo-2
Then run the
docker swarm join command.
docker@swarm-demo-2:~$ docker swarm join --token SWMTKN-1-452450rx24myaxaac49y67qijz5e3zoa84li5vvioy2sbrorhb-3cv994lxh25419huwynze0d0u 192.168.99.100:2377 This node joined a swarm as a worker.
These steps should also be repeated on the swarm-demo-3 virtual machine.
Review the Cluster
We now have a fully functional docker swarm cluster created. If we ssh into the swarm manager, we can use the
docker node commands to manage the nodes in the cluster.
Usage: docker node COMMAND Manage Swarm nodes Options: --help Print usage Commands: demote Demote one or more nodes from manager in the swarm inspect Display detailed information on one or more nodes ls List nodes in the swarm promote Promote one or more nodes to manager in the swarm ps List tasks running on one or more nodes, defaults to current node rm Remove one or more nodes from the swarm update Update a node Run 'docker node COMMAND --help' for more information on a command.
Lets run the
docker node ls command to see the status of the cluster.
docker@swarm-demo-1:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 4nz4qdk1ebkccgeyoa58xq4hf swarm-demo-2 Ready Active 6mkvtubrpxxfrp9zdos134e87 * swarm-demo-1 Ready Active Leader n8vmt6pkq1s670h12pcv13tev swarm-demo-3 Ready Active
Deploy to the Swarm Cluster
Applications can be deployed to the swarm cluster using the
docker service create command. When we create our service, we first will specify which image to use. In our case, we will be using the image that was created in the previous post – jrob5756/swarm-demo. To run multiple instances of the image, the
--replicas parameter can be used.
λ docker-machine ssh swarm-demo-1 docker@swarm-demo-1:~$ docker service create --name swarm-demo --publish 5000:5000 jrob5756/swarm-demo v6o00hfu3fptdmt26bzi04r1t
We can now see that our service was created and is running!
docker@swarm-demo-1:~$ docker service ls ID NAME MODE REPLICAS IMAGE v6o00hfu3fpt swarm-demo replicated 1/1 jrob5756/swarm-demo:latest
To make sure everything is working, browse to http://192.168.99.100:5000/api/values which gives us the same output as before. To see the node our service is running on, we can run the
docker service ps command.
docker@swarm-demo-1:~$ docker service ps swarm-demo ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS yrv9hi5kbhw2 swarm-demo.1 jrob5756/swarm-demo:latest swarm-demo-2 Running Running 7 minutes ago
Now the fun part, lets shut down swarm-demo-2 and see what happens! We could run the
docker-machine stop command but, lets simulate a hardware failure. From the VirtualBox Manager, the machine can be powered off directly. Once this is done, our api endpoint becomes unavailable. After about a minute, we can see the service gets switched over to the swarm-demo-1 machine and the site is available again. The
docker node ls command now shows that swarm-demo-2 is in a down status.
docker@swarm-demo-1:~$ docker service ps swarm-demo ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS u8pihel1kb6o swarm-demo.1 jrob5756/swarm-demo:latest swarm-demo-1 Running Running 8 seconds ago yrv9hi5kbhw2 \_ swarm-demo.1 jrob5756/swarm-demo:latest swarm-demo-2 Shutdown Running 18 minutes ago docker@swarm-demo-1:~$ docker node ls ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS 4nz4qdk1ebkccgeyoa58xq4hf swarm-demo-2 Down Active 6mkvtubrpxxfrp9zdos134e87 * swarm-demo-1 Ready Active Leader n8vmt6pkq1s670h12pcv13tev swarm-demo-3 Ready Active
Shortly after starting swarm-demo-2 back up, the machine is automatically returned to the cluster and we are back to normal. That said, we did have a bit of down time. What if we want to avoid any downtime all together? In this case, we can increase the number of replicas that are running of the service. This is done with the
docker service update command.
docker@swarm-demo-1:~$ docker service update swarm-demo --replicas 2 swarm-demo docker@swarm-demo-1:~$ docker service ls ID NAME MODE REPLICAS IMAGE v6o00hfu3fpt swarm-demo replicated 2/2 jrob5756/swarm-demo:latest
The service is now running on both swarm-demo-1 and swarm-demo-2. Lets again stop swarm-demo-2 by powering off the Virtual Machine. This time… NO WAITING!!! I suppose this isn’t a surprise but, it does highlight the importance of scaling critical services across nodes. Furthermore, we see first hand that not only does Docker Swarm provide High-Availability and Failover but, it also provides the ability to easily scale out our services.
To summarize, one of the most powerful aspects of ASP.NET Core is its interoperability. This allows us to run on Linux and take advantage of containerization platforms like Docker. Docker comes equipped with Docker Swarm which provides native clustering capabilities.