How do you implement zero-downtime deployments with Docker Swarm?
Service setup
Your swarm should have 1 manager/leader node and many worker nodes.
Your application also needs to support rolling deployments; this means it can run with multiple versions at once and be aware of running in a multi-node environment. It should not assume that it is by itself and has dedicated access to the database or timed (cron) tasks.
When you create the service you can provide config for --update-parallelism set to 1.
docker service create --name my-service --replicas 3 --update-parallelism 1 --update-delay 10s my-image:1.0This will update each replica task one-by-one. The --update-parallelism 1 setting ensures that only one task is replaced at a time (this is the default behaviour). The --update-delay setting introduces a delay between tasks, so that the rolling restart happens gradually.
If you have a very big swarm, you can increase the parallelism or reduce the update-delay to speed up the deployment.
Update and deployment
To update the service we run the service update command with the new image label.
docker service update --image my-image:2.0 my-serviceIn case of a problem, we can trigger a rollback via this command.
docker service update --rollback-config parallelism=1 --rollback my-serviceCanary deployment
Docker Swarm does support updating a limited number of replicas in a service, so you can introduce a canary deployment by updating just one task in the service.
docker service update --replicas 1 --image my-image:2.1 my-serviceReference
Official documentation: Docker service update docs.
The two settings to get right are the update order (starting the new task before stopping the old one, rather than the reverse) and a defined healthcheck on the service — without a healthcheck, Swarm has no way to know a new task is actually ready before routing traffic to it.