Docker Swarm
Set up Docker Swarm for container orchestration across multiple servers, simpler than Kubernetes, built into Docker
Docker Swarm is Docker's built-in container orchestration system. It's simpler than Kubernetes and ideal for teams that already use Docker Compose and want multi-server deployments without the complexity of K8s.
When to use Swarm vs K3s
- Docker Swarm, you already use Docker Compose, want minimal ops overhead, small to medium scale
- K3s, need more features (autoscaling, advanced networking), larger scale, more ecosystem support
Architecture
Manager Node (orchestrates, schedules)
├── Worker Node 1 (runs containers)
├── Worker Node 2 (runs containers)
└── Worker Node 3 (runs containers)For HA, use 3 or 5 manager nodes. For simplicity, 1 manager + N workers works fine.
Initialize the swarm (on the manager)
docker swarm init --advertise-addr YOUR_MANAGER_IPThis outputs a join token. Save it, you'll need it to add workers.
Check the swarm status:
docker node lsAdd worker nodes
On each worker server, run the join command from the init output:
docker swarm join --token SWMTKN-1-xxxxx MANAGER_IP:2377If you lost the token, regenerate it on the manager:
docker swarm join-token workerFirewall rules (between nodes)
# On all nodes: open Swarm ports
sudo ufw allow 2377/tcp # Cluster management
sudo ufw allow 7946/tcp # Node communication
sudo ufw allow 7946/udp
sudo ufw allow 4789/udp # Overlay networkDeploy a stack
Docker Swarm uses the same docker-compose.yml format with a few additions. Create a stack file:
nano docker-stack.ymlversion: '3.8'
services:
web:
image: nginx:alpine
ports:
- "80:80"
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
- webnet
api:
image: myapp:latest
deploy:
replicas: 2
resources:
limits:
cpus: '0.5'
memory: 256M
networks:
- webnet
networks:
webnet:
driver: overlayDeploy:
docker stack deploy -c docker-stack.yml myappManage stacks and services
# List stacks
docker stack ls
# List services in a stack
docker stack services myapp
# List running tasks (containers)
docker stack ps myapp
# Scale a service
docker service scale myapp_web=5
# Update a service image
docker service update --image nginx:1.25 myapp_web
# Rolling update
docker service update \
--update-parallelism 1 \
--update-delay 30s \
--image myapp:v2 \
myapp_api
# Remove a stack
docker stack rm myappSecrets management
Swarm has built-in encrypted secrets:
# Create a secret
echo "mysecretpassword" | docker secret create db_password -
# Or from a file
docker secret create ssl_cert ./cert.pem
# List secrets
docker secret lsUse in stack file:
services:
db:
image: mysql:8
secrets:
- db_password
environment:
MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
external: trueOverlay networks
Services in the same overlay network can communicate by service name:
networks:
backend:
driver: overlay
encrypted: true # Encrypt traffic between nodesFrom inside a container in the backend network:
curl http://api:3000/healthShared storage with NFS
Swarm doesn't handle persistent storage natively. Use NFS or a distributed volume driver:
services:
web:
image: nginx
volumes:
- webdata:/var/www/html
volumes:
webdata:
driver: local
driver_opts:
type: nfs
o: "addr=10.0.0.1,rw"
device: ":/exports/webdata"Monitor the swarm
# Node status
docker node ls
# Service status
docker service ls
# Inspect a service (see placement, ports, replicas)
docker service inspect myapp_web --pretty
# Live log from all replicas of a service
docker service logs -f myapp_web
# Events
docker eventsPromote a worker to manager
docker node promote worker1Demote:
docker node demote worker1Drain a node (for maintenance)
# Move all containers off a node
docker node update --availability drain worker1
# Bring it back
docker node update --availability active worker1Leave the swarm
On a worker:
docker swarm leaveOn the manager (force):
docker swarm leave --force