Scalable, and highly available (and Over engineered) "Hello, world" stack
Building on what we've learned in previous posts about Docker, in this blog post, we will implement an over engineered Hello world service.
This will be deployed on a Docker Swarm cluster, and will be composed of 3 services:
- hello-svc: will handle answering the "Hello" part
- world-svc: will handle answering the "world" part
- hello-world-svc: will locate (read service discovery) the hello-svc and the world-svc and will query both to construct the "Hello, world" we love! (Some reactive code RxJS inside!)
Let's get going.
Here I scaled the Hello Service to 5, because in France we say Hello frequently ;)
Init Swarm
Start by setting up our Swarm. The usual docker swarm init and docker swarm join command are to be used. Check this post if you need an F5er.
docker swarm init
docker swarm join --token ... ...
docker swarm join --token ... ...
docker swarm join --token ... ...
Start a Swarm Visualizer to follow along
docker run -it -d -p 8080:8080 -e HOST=stratus-clay -v /var/run/docker.sock:/var/run/docker.sock manomarks/visualizer
Head over to http://your-host:8080 to see your Visualizer. Mine is at http://stratus-clay:8080
Time to build our Services.
Build
The aim of this post is not to get into the code details, so go ahead and clone https://github.com/jmkhael/docker-playground to follow along.
Our Hello, and World service will resemble a lot what we already built in the post Microservice heaven with Docker. The returned strings are different...
The Hello-world service is a bit different, in a sense that it integrates and builds on other services. It is in practice a mashup of 2 services, hello-svc and world-svc. It's "Business" code is different.
If you need to rebuild and push the docker images, you can find below the commands:
Build Hello
docker build -t jmkhael/hello:0.0.1 .
docker push jmkhael/hello:0.0.1
Build World
docker build -t jmkhael/world:0.0.1 .
docker push jmkhael/world:0.0.1
Build Hello-World
docker build -t jmkhael/hello-world:0.0.1-rc1 .
docker push jmkhael/hello-world:0.0.1-rc1
Ok. Now, at least in theory, we have what is needed to build our Hello, world Stack offering :)
Deploying the Hello world Stack
We need to deploy our 3 services, and they need to be able to communicate together.
For that to happen, we need to create an overlay network, which will span the Swarm cluster scope.
Then we will create our 3 services like we already did in previous posts, but this time attach them to the network we created. The section below details the commands to achieve that.
Create Network and attach Services
docker network create --driver overlay hello-world-network
docker service create --name hello-svc --network hello-world-network --publish 10000:5000 jmkhael/hello:0.0.1
docker service create --name world-svc --network hello-world-network --publish 20000:5000 jmkhael/world:0.0.1
docker service create --name hello-world-svc --network hello-world-network --publish 30000:5000 jmkhael/hello-world:0.0.1
At this point, opening the urls of the published service, we should see the thing working :)
http://stratus-clay:10000, http://stratus-clay:20000, http://stratus-clay:30000
Cleanup
Like every good citizen, we will cleanup after us.
docker service rm hello-svc world-svc hello-world-svc; docker network rm hello-world-network
Iterative development
Create development instance constrained to a known host (because!)
docker build -t jmkhael/hello-world:develx .
docker service create --name devel --network hello-world-network --publish 1234:5000 --constraint 'node.hostname==stratus-clay' jmkhael/hello-world:develx
Upgrade devel image
docker service update devel --image jmkhael/hello-world:develx
time to test it and see that it works...
docker service update devel --image jmkhael/hello-world:develx
Once ready, you can update the "official" production hello-world service by tagging the build which worked:
docker build -t jmkhael/hello-world:0.0.1-rc1 .
docker push jmkhael/hello-world:0.0.1-rc1
docker service update hello-world-svc --image jmkhael/hello-world:0.0.1-rc1
Extra credit exercises
Visualization with Portainer on swarm
docker run -d -p 9008:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer --swarm
Visualization with Portainer service deployed globally
docker service create --name portainer-svc --publish 9009:9000 --mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock --mode global portainer/portainer
Overlay network customization for subnet/gateway/encryption...
docker network create --driver overlay --subnet 33.0.9.0/24 hello-world-network
docker network create --driver overlay --subnet 200.0.9.0/24 --gateway 200.0.9.254 hello-world-network