Docker Compose files designed for single-host development can be extended to run on Docker Swarm clusters through the deploy section. This section contains all Swarm-specific configuration, including replica counts, placement constraints, update policies, and rollback strategies. Understanding how to properly configure the deploy section transforms your Compose files from development tools into production-ready stack definitions.
Understanding the Deploy Section
The deploy section is ignored by standard docker-compose commands and only takes effect when deploying to a Swarm using docker stack deploy. This separation allows a single Compose file to work both locally and in Swarm mode.
version: '3.8'
services:
web:
image: nginx:alpine
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
When you run docker-compose up, the deploy section is ignored. When you run docker stack deploy -c docker-compose.yml mystack, only the deploy configuration applies.
Basic Replica Configuration
The most fundamental Swarm configuration is specifying the number of service replicas:
version: '3.8'
services:
api:
image: myapp/api:latest
deploy:
replicas: 5
This creates five identical containers running the API service, distributed across available Swarm nodes. The Swarm scheduler automatically places replicas on different nodes for high availability.
Replicated vs Global Mode
Services can run in two modes:
Replicated mode (default): Runs a specified number of replicas
services:
api:
image: myapp/api:latest
deploy:
mode: replicated
replicas: 3
Global mode: Runs exactly one replica on every Swarm node
services:
monitoring:
image: prometheus/node-exporter
deploy:
mode: global
Global mode is ideal for node-level services like monitoring agents, log collectors, or network proxies that need to run on every node in the cluster.
Placement Constraints
Control where services run using placement constraints:
version: '3.8'
services:
database:
image: postgres:14
deploy:
placement:
constraints:
- node.role == manager
- node.labels.storage == ssd
This restricts the database to run only on manager nodes that have the storage=ssd label.
Common constraint patterns:
- node.role == manager: Run only on manager nodes
- node.role == worker: Run only on worker nodes
- node.hostname == node1: Run on a specific node
- node.labels.key == value: Match custom node labels
Multiple Placement Constraints
Combine constraints for precise placement:
services:
cache:
image: redis:alpine
deploy:
replicas: 3
placement:
constraints:
- node.role == worker
- node.labels.tier == cache
- node.labels.datacenter == primary
All constraints must be satisfied for a replica to be placed on a node. This ensures cache services run only on worker nodes in the primary datacenter with the cache tier label.
Placement Preferences
While constraints are absolute requirements, preferences express preferred placement that the scheduler tries to honor:
services:
web:
image: nginx:alpine
deploy:
replicas: 6
placement:
preferences:
- spread: node.labels.datacenter
This spreads replicas evenly across nodes with different datacenter label values, improving availability by distributing services across failure domains.
Multiple preferences create layered distribution:
services:
api:
image: myapp/api:latest
deploy:
replicas: 9
placement:
preferences:
- spread: node.labels.datacenter
- spread: node.labels.rack
This first spreads across datacenters, then spreads within each datacenter across racks.
Maximum Replicas Per Node
Limit how many replicas can run on a single node:
services:
worker:
image: myapp/worker:latest
deploy:
replicas: 10
placement:
max_replicas_per_node: 2
Even with 10 replicas, no single node will run more than 2 worker instances. This prevents resource saturation on individual nodes and improves fault tolerance.
Update Configuration
Control how services are updated when deploying new versions:
services:
api:
image: myapp/api:latest
deploy:
replicas: 6
update_config:
parallelism: 2
delay: 10s
failure_action: rollback
monitor: 30s
max_failure_ratio: 0.3
order: stop-first
Update parameters:
- parallelism: Number of replicas to update simultaneously
- delay: Time to wait between update batches
- failure_action: Action when update fails (pause, continue, rollback)
- monitor: Time to monitor each task for failures after update
- max_failure_ratio: Fraction of tasks allowed to fail during update
- order: Update order (stop-first or start-first)
Update Order Strategies
The order parameter controls how replicas are replaced:
Stop-first (default): Stop old replica before starting new one
deploy:
update_config:
order: stop-first
This ensures no over-provisioning of resources but causes temporary capacity reduction.
Start-first: Start new replica before stopping old one
deploy:
update_config:
order: start-first
This maintains full capacity during updates but temporarily requires extra resources.
Rollback Configuration
Define how automatic rollbacks behave when updates fail:
services:
api:
image: myapp/api:latest
deploy:
replicas: 5
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
rollback_config:
parallelism: 2
delay: 5s
failure_action: pause
monitor: 20s
max_failure_ratio: 0.2
order: stop-first
Rollback configuration mirrors update configuration but controls the rollback process. When an update fails and triggers a rollback, these parameters determine how quickly and safely the service returns to its previous state.
Restart Policy Configuration
Specify how Swarm handles container failures:
services:
web:
image: nginx:alpine
deploy:
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
window: 120s
Restart policy parameters:
- condition: When to restart (none, on-failure, any)
- delay: Time to wait before restart attempts
- max_attempts: Maximum restart attempts before giving up
- window: Time window for evaluating restart attempts
If a container fails max_attempts times within window, Swarm stops trying to restart it.
Endpoint Mode Configuration
Control how traffic routes to service replicas:
services:
web:
image: nginx:alpine
ports:
- "80:80"
deploy:
replicas: 3
endpoint_mode: vip
Endpoint modes:
- vip (default): Virtual IP mode with built-in load balancing
- dnsrr: DNS round-robin without load balancer
VIP mode provides better load distribution and connection handling, while DNS round-robin offers simpler networking for clients that handle load balancing themselves.
Labels for Services and Containers
Add metadata to services and their containers:
services:
api:
image: myapp/api:latest
deploy:
labels:
com.example.service.type: "api"
com.example.version: "2.0"
replicas: 3
labels:
com.example.container.type: "api-instance"
Labels in the deploy section apply to the Swarm service, while labels outside deploy apply to individual containers. Service labels are used by orchestration tools and management systems, while container labels are visible to monitoring and logging agents.
Service-Level Resource Reservations
Request guaranteed resources for service replicas:
services:
database:
image: postgres:14
deploy:
replicas: 2
resources:
reservations:
cpus: '1.0'
memory: 2G
Reservations tell the Swarm scheduler to only place replicas on nodes with available resources. If no node has sufficient resources, the replica remains in pending state.
Service-Level Resource Limits
Set maximum resource usage for replicas:
services:
worker:
image: myapp/worker:latest
deploy:
replicas: 5
resources:
limits:
cpus: '2.0'
memory: 4G
Limits prevent individual replicas from consuming excessive resources, protecting other services on the same node.
Combined Resource Configuration
Use both reservations and limits for comprehensive resource management:
services:
api:
image: myapp/api:latest
deploy:
replicas: 4
resources:
reservations:
cpus: '0.5'
memory: 512M
limits:
cpus: '2.0'
memory: 2G
This configuration guarantees each replica at least 0.5 CPU and 512MB memory while preventing it from exceeding 2 CPU and 2GB memory.
Generic Resources for Specialized Hardware
Allocate specialized hardware resources like GPUs:
services:
ml-processor:
image: myapp/ml:latest
deploy:
replicas: 2
resources:
reservations:
generic_resources:
- discrete_resource_spec:
kind: 'gpu'
value: 1
This reserves one GPU for each replica. Nodes must advertise GPU availability for the scheduler to place these replicas appropriately.
Deployment Mode for Testing
Configure services that run once for initialization or testing:
services:
database-migrator:
image: myapp/migrator:latest
deploy:
restart_policy:
condition: none
replicas: 1
With condition: none, the service runs once and isn't restarted on failure, suitable for one-time tasks like database migrations or data initialization.
Update and Rollback Monitoring
Fine-tune failure detection during updates:
services:
api:
image: myapp/api:latest
deploy:
replicas: 10
update_config:
parallelism: 2
delay: 15s
monitor: 60s
max_failure_ratio: 0.1
failure_action: rollback
With a 60-second monitor window and 10% maximum failure ratio, if more than one replica (10% of 10) fails within 60 seconds of update, the entire update automatically rolls back.
Complex Placement Scenarios
Combine constraints and preferences for sophisticated placement:
services:
frontend:
image: myapp/frontend:latest
deploy:
replicas: 9
placement:
constraints:
- node.role == worker
- node.labels.tier == web
preferences:
- spread: node.labels.zone
- spread: node.labels.rack
max_replicas_per_node: 2
This ensures frontend replicas run only on web-tier worker nodes, spreads them across availability zones and racks, and limits node saturation by capping replicas per node.
Service Dependencies in Swarm
While Swarm doesn't enforce startup order like depends_on does locally, you can influence service startup timing:
version: '3.8'
services:
database:
image: postgres:14
deploy:
replicas: 1
restart_policy:
condition: on-failure
delay: 5s
api:
image: myapp/api:latest
deploy:
replicas: 3
restart_policy:
condition: on-failure
delay: 10s
The API's longer restart delay gives the database time to initialize first. For more robust dependency handling, applications should implement connection retry logic.
Rolling Back to Specific Versions
Swarm maintains service version history, enabling rollback to previous states:
docker service update --rollback mystack_api
Configure how far back rollbacks can go:
services:
api:
image: myapp/api:latest
deploy:
replicas: 5
rollback_config:
parallelism: 2
delay: 5s
failure_action: pause
When triggered, Swarm reverts to the previous service configuration, not just the previous image.
Update Failure Scenarios
Handle various failure conditions appropriately:
services:
critical-service:
image: myapp/critical:latest
deploy:
replicas: 5
update_config:
parallelism: 1
delay: 30s
monitor: 60s
failure_action: pause
max_failure_ratio: 0
With max_failure_ratio: 0 and failure_action: pause, any failure during update pauses the rollout, requiring manual intervention. This is appropriate for critical services where partial updates are unacceptable.
For less critical services, allow some failure:
services:
batch-processor:
image: myapp/processor:latest
deploy:
replicas: 20
update_config:
parallelism: 5
delay: 10s
failure_action: continue
max_failure_ratio: 0.25
This continues updating even if up to 25% of replicas fail, accepting some disruption in exchange for completing the deployment.
Phased Deployment Strategies
Implement canary deployments through careful update configuration:
services:
api:
image: myapp/api:v2
deploy:
replicas: 10
update_config:
parallelism: 1
delay: 120s
monitor: 180s
max_failure_ratio: 0.1
failure_action: rollback
With single-replica parallelism and long delays, you can observe each new replica's behavior extensively before proceeding. If issues arise, automatic rollback protects the remaining replicas.
Label-Based Service Selection
Use labels to select services for operations:
services:
frontend:
image: myapp/frontend:latest
deploy:
labels:
com.example.tier: "presentation"
com.example.team: "frontend-team"
replicas: 3
api:
image: myapp/api:latest
deploy:
labels:
com.example.tier: "application"
com.example.team: "backend-team"
replicas: 5
Labels enable filtering and bulk operations:
docker service ls --filter label=com.example.tier=application
This lists only services with the specified label, useful for managing large stacks with many services.
Graceful Service Shutdown
Configure how Swarm handles container termination:
services:
worker:
image: myapp/worker:latest
stop_grace_period: 60s
deploy:
replicas: 5
update_config:
parallelism: 1
delay: 30s
The stop_grace_period gives containers time to finish in-progress work before forceful termination. During updates, new replicas start while old ones gracefully shut down, minimizing disruption.
Service Lifecycle Management
A complete service configuration for production:
version: '3.8'
services:
api:
image: myapp/api:v1.5.0
stop_grace_period: 30s
deploy:
mode: replicated
replicas: 8
labels:
com.example.service: "api"
com.example.version: "1.5.0"
update_config:
parallelism: 2
delay: 20s
failure_action: rollback
monitor: 45s
max_failure_ratio: 0.2
order: start-first
rollback_config:
parallelism: 4
delay: 10s
failure_action: pause
monitor: 30s
max_failure_ratio: 0.1
order: stop-first
restart_policy:
condition: on-failure
delay: 10s
max_attempts: 5
window: 180s
placement:
constraints:
- node.role == worker
- node.labels.tier == application
preferences:
- spread: node.labels.zone
max_replicas_per_node: 3
resources:
reservations:
cpus: '0.5'
memory: 512M
limits:
cpus: '2.0'
memory: 2G
endpoint_mode: vip
This configuration provides comprehensive control over service deployment, updates, placement, and recovery.
Stack Deployment Command
Deploy your configured stack to Swarm:
docker stack deploy -c docker-compose.yml mystack
This creates or updates all services defined in the Compose file according to their deploy configurations.
View deployed services:
docker stack services mystack
Remove the stack:
docker stack rm mystack
Updating Running Stacks
Modify the Compose file and redeploy to update services:
services:
api:
image: myapp/api:v1.6.0 # Changed from v1.5.0
deploy:
replicas: 10 # Increased from 8
# Other configuration unchanged
Redeploy the stack:
docker stack deploy -c docker-compose.yml mystack
Swarm detects changes and updates only affected services according to their update configuration.
Service-Specific Update Policies
Different services may need different update strategies:
version: '3.8'
services:
frontend:
image: myapp/frontend:latest
deploy:
replicas: 5
update_config:
parallelism: 5 # Update all at once
delay: 0s
order: start-first
api:
image: myapp/api:latest
deploy:
replicas: 10
update_config:
parallelism: 2 # Gradual rollout
delay: 30s
order: start-first
database:
image: postgres:14
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 0s
order: stop-first # Prevent split-brain
The frontend can update quickly since it's stateless, the API updates gradually to ensure stability, and the database updates conservatively to prevent data issues.
Combining Local and Swarm Configuration
A single Compose file can support both local development and Swarm deployment:
version: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
# Used locally
restart: unless-stopped
# Used in Swarm
deploy:
replicas: 3
restart_policy:
condition: on-failure
When running docker-compose up, the restart field applies. When running docker stack deploy, the deploy section applies.
Node Availability and Service Placement
Services react to node availability changes:
services:
api:
image: myapp/api:latest
deploy:
replicas: 6
placement:
constraints:
- node.role == worker
When a worker node becomes unavailable, Swarm automatically reschedules its replicas to remaining healthy nodes, maintaining the desired replica count.
Deployment Strategies for Different Service Types
Stateless services: Aggressive parallel updates
services:
stateless-api:
image: myapp/api:latest
deploy:
replicas: 10
update_config:
parallelism: 5
delay: 5s
Stateful services: Conservative sequential updates
services:
stateful-processor:
image: myapp/processor:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 60s
monitor: 120s
Singleton services: Zero-downtime updates with start-first
services:
scheduler:
image: myapp/scheduler:latest
deploy:
replicas: 1
update_config:
parallelism: 1
order: start-first
Monitoring Deployment Progress
Track deployment status in real-time:
docker service ps mystack_api
This shows all tasks (replicas) for the service, including their current state, desired state, node assignment, and error messages.
Watch updates as they progress:
watch docker service ps mystack_api
This continuously refreshes the view, showing updates rolling across replicas.
Deployment Rollback Triggers
Configure when automatic rollbacks should occur:
services:
critical-service:
image: myapp/critical:latest
deploy:
replicas: 8
update_config:
parallelism: 2
delay: 30s
monitor: 90s
max_failure_ratio: 0.125 # 1 out of 8
failure_action: rollback
If any single replica fails within its 90-second monitoring window during update, the entire deployment rolls back. This extremely conservative approach protects critical services.
Best Practices for Deploy Configuration
Start with conservative update policies: Begin with low parallelism and long delays, then optimize based on observed stability.
Match update order to service type: Use start-first for stateless services and stop-first for stateful services or singletons.
Set appropriate monitoring windows: Longer monitoring catches delayed failures but slows deployments. Balance based on your application's failure patterns.
Use placement constraints strategically: Constrain services to appropriate node types but avoid over-constraining, which limits scheduling flexibility.
Implement proper restart policies: Configure restart policies that match your service's failure recovery characteristics.
Test rollback procedures: Regularly verify that rollback configurations work as expected by intentionally deploying failing versions.
Label extensively: Use labels to document service characteristics, ownership, and purpose for easier management.
Document update strategies: Comment your deploy configurations explaining the reasoning behind parameter choices.
Monitor resource usage: Ensure reservations match actual requirements and limits prevent resource exhaustion.
Plan for node failures: Design placement strategies and replica counts that maintain service availability during node outages.
Use version-specific image tags: Always deploy specific image versions rather than latest for predictable rollbacks.
Implement health checks: While outside the deploy section, health checks are critical for successful updates and rollbacks.
Docker Swarm's deploy section transforms Compose files into production orchestration configurations. By properly configuring replicas, placement, updates, rollbacks, and restart policies, you can deploy services that scale horizontally, update safely, recover automatically, and distribute intelligently across your cluster. The deploy section provides the foundation for running containerized applications at scale with high availability and operational resilience.