Using Docker Swarm to do Service Discovery and Deploy like a God

Walisson de Deus Casonatto
Quick Mobile Labs
Published in
3 min readSep 27, 2016

The bigger your microservice architecture gets, more difficulties appear. You start to have to worry about factors such as: how to create a continuous deployment, where do these deploys, how services will communicate with each other etc. For your happiness, the new Docker’s version (1:12) easily solves these problems and you no longer need to worry about them.

To follow this guide you’re going to need a Docker Swarm Cluster. Learn how to do it here

First of all, we need to create a network. Swarm has an network driver called overlay, witch is created on every swarm node.

docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt encrypted \
refresh-network

Some hosts may not work with this configuration. I don’t know exactly the reason yet (if you know, leave a comment haha), but the solution is:

docker network create \
--driver overlay \
--subnet 10.0.9.0/24 \
--opt secure \
refresh-network

Networking on swarm requires the following ports unlocked:
udp 4789 Data plane (VXLAN)
tcp/udp 7946 Control plane

Now that we have a common network on every host, it’s time to start our Redis Service:

docker service create --name redis-refresh --network refresh-network --update-delay 10s redis

Notice that I did not publish any port to Redis. I did it because our services will communicate through the network (that’s why the need to create a network in common for all). You only need to publish the port when you need to publicly access the service.

docker service create --name refresh --publish 80:80 --network refresh-network --update-delay 10s walissoncasonatto/go-refresh

On my new service above I exposed the port 80 to remote connections. As I said, once you do it, this service will be available on every node on port 80. Sorry, but you can’t have 2 different services on same port on a Swarm Cluster. However, it can be easily solved with a proxy service.

The service exposed on port 80 has the following code:

package mainimport (
“fmt”
“net/http”
“github.com/fiorix/go-redis/redis”
)
func handler(w http.ResponseWriter, r *http.Request) {
cliente := r.URL.Path[1:]
c := redis.New(“redis-refresh:6379”)
c.SAdd(“clients”,cliente)
c.IncrBy(cliente,1)
clientes,_ := c.SMembers(“clients”)
for _,element := range clientes {
quantidade,_ := c.Get(element)
fmt.Fprintf(w, “%s : %s \n”, element,quantidade)
}
}
func main() {
http.HandleFunc(“/”, handler)
http.ListenAndServe(“:80”, nil)
}

Note that in Redis’s connection we only specify the service name (redis-refresh). No matter where the Redis is going to be deployed, swarm is going to resolve that name for us. However, they need to be on the same network.

If you are wondering what is the option update-delay 10s… It is used to role update. So, you can update without downtime. You just need to scale your service up and then updating, then after it you can scale it down.

You can update most of the services properties with update command, for example:

docker service scale refresh=3
docker service update --image walissoncasonatto/go-refresh:novo refresh

You can access your application and keep refreshing the page, it will have no downtime.

Using Docker Swarm you no longer will need to worry about where you’re going to deploy your applications, and you also have some nice features like service discovery and role-update to play with.

--

--