Scalable, and highly available (and Over engineered) "Hello, world" stack

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.

hello-world-stack

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

hello-world-stack-browser

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