Stacks rather than compose, constraints, replicas, rolling updates & self healing
Docker Swarm - Overview and how to use it
3 min read
Published Jul 13 2025, updated Aug 17 2026
Guide Sections
Guide Comments
A Docker Stack is a higher-level abstraction in Docker used to deploy and manage a group of services on a Docker Swarm cluster. It is the Swarm-native way of orchestrating multi-container applications — similar to Docker Compose — but optimized for production and multi-node clusters.
Stacks allow you to define entire applications (services, networks, volumes, secrets, configs) in a single YAML file and deploy them across a distributed set of nodes.
Docker Compose vs Docker Stack
Feature | Docker Compose | Docker Stack |
Scope | Single host | Multi-host (Swarm cluster) |
Mode | Local development | Production/Cluster deployments |
Command |
|
|
Networks | Created per project | Created as Swarm-scoped overlay |
Secrets/Configs | Limited | Full support |
Health checks | Supported | Partially supported in some versions |
Service replicas | Manual scaling | Built-in scaling with replicas |
Load balancing | Requires manual setup | Built-in with Swarm routing mesh |
Restart/Reschedule containers | Manual or basic | Auto-reschedule on failure or update |
Not all Compose features work with Docker Stack (Swarm mode):
build:is limited or unsupported (usedocker buildbeforehand).depends_on:is ignored.container_name:is ignored (since services get auto-named).- Volumes must be defined properly; anonymous volumes behave differently.
healthcheck:behaviour may be limited in Swarm context.
Docker Stack YAML File
Docker Stack uses the same docker-compose.yml format, but not every Compose option is supported (e.g., depends_on, build in Swarm mode is limited).
version: '3.8'services: web: image: myapp:latest deploy: replicas: 3 restart_policy: condition: on-failure placement: constraints: [node.role == worker] ports: - "80:80" redis: image: redis:alpinenetworks: default: driver: overlayDeploying a stack:
docker stack deploy -c docker-compose.yml mystackThis command will:
- Create services from your YAML file.
- Deploy them across the Swarm nodes.
- Manage networks, volumes, secrets as Swarm-scoped resources.
Managing stacks
Show all stacks running in the Swarm:
docker stack lsList all tasks (containers) running under that stack:
docker stack services mystackList services running in the stack:
docker stack services mystackRemove the entire stack (services, networks, etc):
docker stack rm mystackUpdating a stack
The best way to update a stack, is to update the compose file with any changes, and then redeploy the stack. That way the compose file will always be correct for the stack that is deployed. This is the prefered approach over making individual updates via the CLI as it means looking at the compose file is the current state and one source of truth. So make changes to that and redeploy.
You can make changes to your Compose file and then run:
docker stack deploy -c docker-compose.yml mystackDocker will:
- Compare the changes,
- Apply rolling updates (where possible),
- Avoid downtime (if correctly configured).
Stack Compose File Syntax for Deployments
When using Docker Stack, service-level deployment settings go under the deploy: key in your docker-compose.yml file. This is Swarm-specific and not supported by standard docker compose up.
Basic structure:
services: web: image: myapp:latest deploy: replicas: 3 placement: constraints: - node.role == worker resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M restart_policy: condition: on-failure delay: 5s max_attempts: 3 window: 30sReplicas - defines the number of instances of the service to run. Swarm will spread them across the cluster as needed:
deploy: replicas: 5placement.constraints - control where services run based on node labels, roles, or system attributes:
deploy: placement: constraints: - node.role == worker # Only on worker nodes - node.labels.type == api # Custom labelNote: you can add labels to nodes by calling: docker node update --label-add type=api <node-id>.
Define resource limits and reservations:
deploy: resources: limits: cpus: '0.50' # Max CPU usage (in cores) memory: 512M # Max memory reservations: cpus: '0.25' # Minimum guaranteed CPU memory: 256M # Minimum guaranteed memoryLimits enforce caps; reservations help Swarm schedule based on available resources.
Define how Swarm restarts a failed container:
deploy: restart_policy: condition: on-failure delay: 10s max_attempts: 5 window: 60sCustomise rolling update behaviour:
deploy: update_config: parallelism: 2 # Update 2 services at a time delay: 10s # Wait 10s between each batch failure_action: pause # Pause on error (or continue/rollback) monitor: 30s # Monitor health for 30sConfigures rollback behavior if an update fails:
deploy: rollback_config: parallelism: 1 delay: 5sGlobal - Instead of specifying replicas, you can run one instance per node:
deploy: mode: globalAll these combined as an example:
version: '3.8'services: app: image: myorg/myapp:latest deploy: replicas: 4 placement: constraints: - node.labels.env == prod resources: limits: cpus: '0.7' memory: 1G reservations: cpus: '0.3' memory: 512M restart_policy: condition: on-failure delay: 5s max_attempts: 2 update_config: parallelism: 2 delay: 10s rollback_config: parallelism: 1 delay: 5s