Docker Swarm transforms a group of Docker hosts into a single, virtual Docker host, enabling container orchestration across multiple machines. This built-in orchestration solution provides high availability, load balancing, and service discovery with minimal configuration. In this guide, we'll explore Docker Swarm's capabilities through practical examples and real-world scenarios.

Go To...
- Introduction to Docker Swarm
- Swarm Architecture
- Setting Up a Swarm Cluster
- Working with Docker Services
- Deploying Applications with Docker Stack
- Managing Secrets in Swarm
- Scaling and Load Balancing
- High Availability and Fault Tolerance
- Rolling Updates and Rollbacks
- Practical Examples
- Cleanup
- Conclusion
Introduction to Docker Swarm
Docker Swarm is Docker's native clustering and orchestration solution that enables you to manage a cluster of Docker nodes as a single virtual system. This guide is based on our Lab6 Swarm Example from the Docker Practical Guide repository.
Swarm mode provides several key features:
- Cluster Management: Integrated with Docker Engine
- Decentralized Design: No single point of failure
- Declarative Service Model: Define the desired state of your services
- Scaling: Easily scale services up or down
- Load Balancing: Automatically distribute requests across services
- Service Discovery: Built-in DNS for finding services by name
- Rolling Updates: Update containers without downtime
- Security: Automatic TLS encryption and mutual authentication
Swarm Architecture
Docker Swarm consists of two types of nodes:
┌─────────────────────────────────────────────────────────────┐
│ Docker Swarm │
│ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │
│ │ Manager │◄───────────────►│ Manager │ │
│ │ Node │ │ Node │ │
│ │ │ │ │ │
│ └─────┬───────┘ └──────┬──────┘ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ │ │ │ │ │ │
│ │ Worker │ │ Worker │ │ Worker │ │
│ │ Node │ │ Node │ │ Node │ │
│ │ │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
- Manager Nodes: Responsible for the orchestration and cluster management functions
- Worker Nodes: Execute containers
Manager nodes maintain the state of the swarm using the Raft consensus algorithm, while worker nodes simply run containers. In a production environment, it's recommended to have multiple manager nodes for high availability.
Setting Up a Swarm Cluster
Let's start by setting up a Docker Swarm cluster:
Initialize a Swarm
On the first node (which becomes a manager):
docker swarm init --advertise-addr <MANAGER-IP>
This command initializes a new swarm and makes the current node a manager. It outputs a token that can be used to join worker nodes to the swarm.
Join as a Worker Node
To add a worker node to the swarm, run the following command on the worker machine:
docker swarm join --token <WORKER-TOKEN> <MANAGER-IP>:2377
Join as a Manager Node
To add another manager to the swarm for high availability:
# Get the manager join token from an existing manager
docker swarm join-token manager
# Use the token to join as a manager on another node
docker swarm join --token <MANAGER-TOKEN> <MANAGER-IP>:2377
View Swarm Status
# List all nodes in the swarm
docker node ls
# View detailed information about a node
docker node inspect <NODE-ID>
# Display the join tokens
docker swarm join-token worker
docker swarm join-token manager
Working with Docker Services
In Docker Swarm, services are the primary way to run containers. Services provide features like scaling, rolling updates, and load balancing:
Create a Service
# Create a simple web service
docker service create \
--name webserver \
--replicas 3 \
--publish 80:80 \
nginx
This command creates a service named "webserver" with three replicas (instances), all running the nginx image. The service is accessible on port 80 of any node in the swarm.
Service Management Commands
# List all services
docker service ls
# List the tasks (containers) of a service
docker service ps webserver
# Display detailed information about a service
docker service inspect webserver
# View the logs of a service
docker service logs webserver
Update a Service
You can update a running service to change its configuration:
# Scale a service
docker service scale webserver=5
# Update the image of a service
docker service update \
--image nginx:1.21 \
--update-parallelism 2 \
--update-delay 10s \
webserver
# Add a mount to a service
docker service update \
--mount-add type=volume,source=nginx-data,target=/usr/share/nginx/html \
webserver
Remove a Service
docker service rm webserver
Deploying Applications with Docker Stack
Docker Stack allows you to deploy and manage multiple services using a Docker Compose file:
Create a Docker Compose File
Create a docker-compose.yml
file:
version: "3.8"
services:
web:
image: nginx
ports:
- "80:80"
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
volumes:
- web-data:/usr/share/nginx/html
visualizer:
image: dockersamples/visualizer
ports:
- "8080:8080"
deploy:
placement:
constraints: [node.role == manager]
volumes:
- /var/run/docker.sock:/var/run/docker.sock
volumes:
web-data:
Deploy a Stack
# Deploy the stack
docker stack deploy -c docker-compose.yml my-stack
Stack Management Commands
# List all stacks
docker stack ls
# List the services in a stack
docker stack services my-stack
# List the tasks (containers) in a stack
docker stack ps my-stack
# Remove a stack
docker stack rm my-stack
Managing Secrets in Swarm
Docker Swarm provides a secure way to manage sensitive data like passwords, API keys, and certificates:
Create a Secret
# Create a secret from a file
echo "mypassword" | docker secret create db-password -
# Create a secret from standard input
docker secret create api-key - <<EOF
abcdefghijklmnopqrstuvwxyz
EOF
Use Secrets in Services
# Create a service with a secret
docker service create \
--name db \
--secret db-password \
--env DB_PASSWORD_FILE=/run/secrets/db-password \
postgres
List and Remove Secrets
# List all secrets
docker secret ls
# Remove a secret
docker secret rm db-password
Scaling and Load Balancing
One of the key benefits of Docker Swarm is the ability to scale services horizontally:
Scale a Service
# Scale a service to 10 replicas
docker service scale webserver=10
Built-in Load Balancing
Docker Swarm includes a built-in load balancer that automatically distributes incoming requests across all the containers of a service. When you publish a port (e.g., --publish 80:80
), the swarm routing mesh makes the service accessible on that port on every node in the swarm, regardless of whether there's a container of that service running on the node.
Test Load Balancing
# Create a service that returns its container ID
docker service create \
--name whoami \
--replicas 3 \
--publish 8000:8000 \
containous/whoami
# Make multiple requests to see load balancing in action
for i in {1..10}; do curl http://localhost:8000; done
High Availability and Fault Tolerance
Docker Swarm ensures high availability through:
Manager Node Redundancy
For high availability, it's recommended to have:
- 3 managers for small-to-medium swarms
- 5 managers for large swarms (never more than 7)
# Check the quorum status
docker info | grep -A2 "Swarm:"
Automatic Container Recovery
If a worker node fails or is removed from the swarm, Docker automatically reschedules its containers on other available nodes:
# Simulate a node failure
docker node update --availability drain worker1
# Check where containers are rescheduled
docker service ps webserver
Global Services
Services can be deployed in "global" mode, ensuring that one instance runs on every node:
# Create a global service for monitoring
docker service create \
--name node-exporter \
--mode global \
--mount type=bind,source=/proc,target=/host/proc,readonly \
--mount type=bind,source=/sys,target=/host/sys,readonly \
prom/node-exporter \
--path.procfs=/host/proc \
--path.sysfs=/host/sys
Rolling Updates and Rollbacks
Docker Swarm enables zero-downtime updates:
Configure Update Strategy
# Create a service with update configuration
docker service create \
--name webserver \
--replicas 5 \
--update-parallelism 2 \
--update-delay 20s \
nginx:1.20
Perform a Rolling Update
# Update the service with a new image
docker service update \
--image nginx:1.21 \
webserver
Rollback to Previous Version
# Rollback to the previous version
docker service update \
--rollback \
webserver
Practical Examples
Let's implement some practical swarm examples based on our Lab6:
Example 1: Basic Service Deployment
Create a simple web application service:
# Create a service with 3 replicas
docker service create \
--name webapp \
--replicas 3 \
--publish 8080:80 \
nginx:alpine
# Verify deployment
docker service ls
docker service ps webapp
Example 2: Multi-Service Application with Stack
Deploy a multi-service application using Docker Stack:
# docker-compose.yml
version: "3.8"
services:
web:
image: nginx:alpine
ports:
- "80:80"
deploy:
replicas: 2
update_config:
parallelism: 1
delay: 10s
volumes:
- web-content:/usr/share/nginx/html
networks:
- frontend
api:
image: node:14-alpine
command: ["node", "server.js"]
deploy:
replicas: 2
networks:
- frontend
- backend
environment:
- DB_HOST=db
- DB_PORT=5432
db:
image: postgres:13-alpine
volumes:
- db-data:/var/lib/postgresql/data
networks:
- backend
environment:
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
deploy:
placement:
constraints: [node.labels.db == true]
networks:
frontend:
backend:
volumes:
web-content:
db-data:
secrets:
db_password:
external: true
Deploy the stack:
# First create the required secret
echo "mySecurePassword" | docker secret create db_password -
# Label a node for database placement
docker node update --label-add db=true node3
# Deploy the stack
docker stack deploy -c docker-compose.yml my-app
Example 3: Global Service for Monitoring
Deploy monitoring agents to all nodes:
# monitoring-stack.yml
version: "3.8"
services:
node-exporter:
image: prom/node-exporter:latest
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.sysfs=/host/sys"
- "--path.rootfs=/rootfs"
networks:
- monitoring
deploy:
mode: global
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- prometheus-data:/prometheus
configs:
- source: prometheus_config
target: /etc/prometheus/prometheus.yml
networks:
- monitoring
deploy:
placement:
constraints: [node.role == manager]
networks:
monitoring:
volumes:
prometheus-data:
configs:
prometheus_config:
file: ./prometheus.yml
Example 4: Implementing High Availability
Create a highly available service with proper update configuration:
# Create a service with HA configuration
docker service create \
--name ha-webapp \
--replicas 5 \
--publish 80:80 \
--update-parallelism 1 \
--update-delay 30s \
--update-monitor 15s \
--update-failure-action rollback \
--update-max-failure-ratio 0.2 \
--health-cmd "curl -f http://localhost/ || exit 1" \
--health-interval 5s \
--health-retries 3 \
--health-timeout 2s \
nginx:alpine
This service configuration includes:
- 5 replicas for load distribution
- Controlled rolling updates (one at a time)
- Health checks to ensure containers are functioning
- Automatic rollback if too many updates fail
Cleanup
When you've finished experimenting with Docker Swarm, it's important to properly clean up your environment. Docker Swarm resources need to be removed in a specific order, and cleaning up a multi-node environment requires attention to detail.
Removing Services and Stacks
First, remove any running services and stacks:
# List all services
docker service ls
# Remove a specific service
docker service rm webapp
# Remove multiple services
docker service rm webapp api-service db-service
# List all stacks
docker stack ls
# Remove a specific stack
docker stack rm my-app
# Remove monitoring stack
docker stack rm monitoring-stack
Cleaning Up Configs and Secrets
Remove any configs and secrets you've created:
# List all configs
docker config ls
# Remove a config
docker config rm prometheus_config
# List all secrets
docker secret ls
# Remove a secret
docker secret rm db_password
Managing Nodes
If you need to remove nodes from the swarm:
# First, drain the node to move workloads elsewhere
docker node update --availability drain node2
# Check that all services have been rescheduled
docker service ps --filter node=node2
# On the worker node, leave the swarm
docker swarm leave
# For a manager node, use force option
docker swarm leave --force
# On the remaining manager, remove the node completely
docker node rm node2
Dismantling the Entire Swarm
To completely dismantle your swarm:
# Remove all stacks
for stack in $(docker stack ls --format ""); do
docker stack rm $stack
done
# Wait for services to be removed
sleep 10
# On each worker node, run:
docker swarm leave
# On each manager node except the last one, run:
docker swarm leave --force
# On the last manager, run:
docker swarm leave --force
Cleaning Up Lab Environment
For the specific examples in our Lab6:
# Navigate to the lab directory
cd lab6_swarm_example
# Run the cleanup script
./cleanup.sh
# Or manually clean up by removing stacks first
docker stack rm my-app monitoring-stack
# Remove swarm-specific networks
docker network prune
Managing Persistent Data
If you created volumes during your Swarm experiments, you may need to manage them separately:
# List volumes
docker volume ls
# Remove specific volumes
docker volume rm web-content db-data prometheus-data
# Remove all unused volumes
docker volume prune
Verifying Complete Cleanup
Verify all Swarm resources have been cleaned up:
# Verify services are gone
docker service ls
# Verify stacks are gone
docker stack ls
# Check swarm status (should show "inactive" if you've left the swarm)
docker info | grep Swarm
Proper cleanup of your Docker Swarm environment ensures that resources are freed, and you don't encounter conflicts when setting up future environments or experiments.
Conclusion
Docker Swarm provides a straightforward yet powerful solution for container orchestration. Its integration with the Docker Engine makes it an excellent choice for teams already familiar with Docker, as it requires minimal additional learning and configuration.
In this guide, we've explored:
- The architecture of Docker Swarm
- Setting up a swarm cluster
- Working with services and stacks
- Managing secrets securely
- Implementing scaling and load balancing
- Ensuring high availability and fault tolerance
- Performing rolling updates with zero downtime
- Real-world examples of swarm deployments
While Kubernetes has become the dominant container orchestration platform for very large-scale deployments, Docker Swarm remains a valuable tool, especially for small to medium-sized deployments where simplicity and ease of use are priorities.
In the next article in our Docker Practical Guide series, we'll explore advanced Docker build techniques with Bake and BuildKit. Stay tuned!
Are you using Docker Swarm in your production environment? Share your experiences or questions in the comments below!
Join the Discussion
Share your thoughts and insights below
Ready to Comment?
Click the button below to load the discussion and share your thoughts with the community.
Loading Comments...
Please wait while we load the discussion.