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.

Table of Contents #
- 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!