Docker Swarm is Docker's built-in container orchestration that turns multiple Docker hosts into a single virtual host. It provides service discovery, load balancing, rolling updates, and secret management with minimal complexity compared to Kubernetes. This guide covers deploying a production Docker Swarm cluster.
Swarm Architecture
- Manager nodes — handle cluster management, scheduling, and API requests
- Worker nodes — run container workloads
- Services — the desired state of containers (replicas, networks, volumes)
Initialize the Swarm
# On the first manager node
docker swarm init --advertise-addr 10.0.0.1
# Output includes join tokens for workers and managers
# To add a worker:
docker swarm join --token SWMTKN-1-abc123... 10.0.0.1:2377
# To add another manager:
docker swarm join-token manager
docker swarm join --token SWMTKN-1-xyz789... 10.0.0.1:2377
Deploying Services
# Create a service
docker service create --name web --replicas 3 --publish 80:80 nginx
# Scale a service
docker service scale web=5
# Update a service (rolling update)
docker service update --image nginx:1.27 --update-parallelism 1 --update-delay 30s web
# List services
docker service ls
# Inspect service tasks
docker service ps web
Docker Stack (Compose for Swarm)
# stack.yml
version: "3.8"
services:
web:
image: nginx:latest
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
order: start-first
rollback_config:
parallelism: 1
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
resources:
limits:
cpus: "0.5"
memory: 256M
ports:
- "80:80"
networks:
- frontend
api:
image: myapp/api:latest
deploy:
replicas: 2
secrets:
- db_password
networks:
- frontend
- backend
db:
image: postgres:16
deploy:
placement:
constraints: [node.role == manager]
volumes:
- db_data:/var/lib/postgresql/data
secrets:
- db_password
networks:
- backend
networks:
frontend:
backend:
internal: true
volumes:
db_data:
secrets:
db_password:
external: true
# Deploy the stack
docker stack deploy -c stack.yml myapp
# List stacks
docker stack ls
# List stack services
docker stack services myapp
# Remove stack
docker stack rm myapp
Secrets Management
# Create a secret
echo "MyDBPassword123!" | docker secret create db_password -
docker secret create tls_cert /path/to/cert.pem
# List secrets
docker secret ls
# Use in service
docker service create --name api --secret db_password myapp/api
# Secret available at /run/secrets/db_password inside the container
Node Management
# List nodes
docker node ls
# Drain a node (for maintenance)
docker node update --availability drain node-name
# Bring back online
docker node update --availability active node-name
# Add labels for placement constraints
docker node update --label-add zone=us-east node-name
# Use labels in placement
deploy:
placement:
constraints: [node.labels.zone == us-east]
Monitoring
# Service logs
docker service logs -f web
# Visualizer (web dashboard)
docker service create --name viz --publish 8080:8080 \
--constraint node.role==manager \
--mount type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \
dockersamples/visualizer
Best Practices
- Use 3 or 5 manager nodes for high availability (odd numbers for quorum)
- Keep managers as managers — run workloads on worker nodes only
- Use Docker secrets instead of environment variables for sensitive data
- Set resource limits on all services to prevent resource starvation
- Use rolling updates with
order: start-firstfor zero-downtime deployments - Drain nodes before maintenance to gracefully reschedule tasks