Single host deployment: docker compose vs docker stack deploy (bridge driver, swarm scope) vs docker stack deploy (overlay driver)

In a setting where you are deploying to production a simple app on a single host, what are the benefits and drawbacks of these three options:

  • simply use docker compose, like in development
  • create a network with --driver=bridge, --scope=swarm and use swarm mode via docker stack deploy
  • use docker stack deploy, which by default creates a network with --driver=overlay

In both the second and third options, the single host/node acts as manager and worker.

I would say that the second option is more adequate, but it is not well-documented. I’m not sure what are the side effects of using this non-default option.

If you have a single host, use docker compose, don’t make life complicated.

If you have (or plan for) multiple hosts, then use Docker Swarm with Overlay and docker stack deploy.

Note that docker stack deploy does not offer all the features, some like privileged or device are missing.

Docker compose does not offer features like automatic shutdown of unhealthy containers though.

That’s true. You have restart: always, but no health check which kicks in when the container does not exit or crash.

Comparing between bridge network and overlay network, for docker stack deploy. With bridge we:

  • lose the ability to perform DNS lookup using tasks.${service name}
  • lose the ability to send requests to ${stack name}_${service name}

When we use overlay network we can send requests to ${stack name}_${service name} which are then load balanced to each task.

So if we use docker stack deploy with bridge network we end up in a weird, worst of both worlds, scenario where we get the DNS capabilities of docker compose, but since in swarm-mode container names are not sequentially set (and therefore impossible to predict) we can not easily find them in the network.

This is even more problematic because network aliases don’t seem to be working in swarm mode, there are tons of issues on github reporting this. The only current workaround seems to be setting hostname for the service, which also sets a new network alias. And then lookup DNS records using that name. This also has the implication that now every task gets the same hostname…

It would be interesting to know if the performance gains (if there are any) from the simpler network driver can outweigh all these negative effects.

Check Swarm with dnsrr (doc):

If you configure a service to use DNS round-robin (DNSRR) service discovery, there is not a single virtual IP. Instead, Docker sets up DNS entries for the service such that a DNS query for the service name returns a list of IP addresses, and the client connects directly to one of these.

DNS round-robin is useful in cases where you want to use your own load balancer, such as HAProxy.

I don’t think DNSRR is supported in bridge network, even if we set the scope to swarm.

You might find this post about swarm template placeholders useful: Example usage of docker swarm template placeholders. They can be in hostnames as well.

1 Like