How to Set Up Docker Swarm for Self-Hosting
What Is Docker Swarm?
Docker Swarm is Docker’s built-in container orchestration mode. It turns a group of Docker hosts into a single virtual host, with service discovery, load balancing, rolling updates, and secret management. Unlike Kubernetes, there’s nothing extra to install — if you have Docker, you have Swarm. It’s the simplest path from “docker compose up” to multi-node orchestration.
Prerequisites
- Two or more Linux servers (Ubuntu 22.04+ recommended) for a cluster, or one for testing
- Docker installed on each node (Docker install guide)
- 512 MB of RAM minimum per node
- Ports open between nodes: 2377/TCP (management), 7946/TCP+UDP (node communication), 4789/UDP (overlay network)
- All nodes must be able to reach each other on these ports
Setup
Initialize Swarm Mode
On your first (manager) node:
docker swarm init --advertise-addr <MANAGER-IP>
This outputs a docker swarm join command with a token. Save this command.
Swarm initialized: current node (abc123) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-xxx <MANAGER-IP>:2377
Add Worker Nodes
On each worker node, run the join command from the init output:
docker swarm join --token SWMTKN-1-xxx <MANAGER-IP>:2377
Verify the Cluster
On the manager node:
docker node ls
You should see all nodes listed with their status and role (Manager/Worker).
Initial Setup
Deploy Your First Service
# Deploy nginx with 3 replicas
docker service create \
--name web \
--replicas 3 \
--publish published=80,target=80 \
nginx:1.27
# Check service status
docker service ls
docker service ps web
Swarm automatically distributes replicas across nodes and load balances incoming traffic.
Deploy a Stack (Compose in Swarm)
Create a docker-compose.yml (Swarm uses the same format with a deploy section):
# stack.yml
services:
web:
image: nginx:1.27
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
ports:
- "80:80"
visualizer:
image: dockersamples/visualizer:stable
ports:
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
placement:
constraints:
- node.role == manager
Deploy the stack:
docker stack deploy -c stack.yml myapp
docker stack services myapp
Configuration
Manager High Availability
For HA, promote additional nodes to manager:
# Get manager join token
docker swarm join-token manager
# On additional manager nodes
docker swarm join --token SWMTKN-1-manager-token <MANAGER-IP>:2377
Run 3 or 5 manager nodes for fault tolerance (Raft consensus requires a majority).
Overlay Networks
Create encrypted overlay networks for inter-service communication:
docker network create \
--driver overlay \
--opt encrypted \
--attachable \
my-network
Services on the same overlay network can reach each other by service name.
Secrets Management
Store sensitive data securely:
# Create a secret
echo "my-password" | docker secret create db_password -
# Use in a service
docker service create \
--name db \
--secret db_password \
postgres:16
Inside the container, the secret is available at /run/secrets/db_password.
Configs
Store non-sensitive configuration files:
# Create a config from a file
docker config create nginx-conf nginx.conf
# Mount in a service
docker service create \
--name web \
--config source=nginx-conf,target=/etc/nginx/nginx.conf \
nginx:1.27
Rolling Updates
# Update service image with zero-downtime rolling update
docker service update \
--image nginx:1.28 \
--update-parallelism 1 \
--update-delay 10s \
web
Resource Limits
deploy:
resources:
limits:
cpus: '0.5'
memory: 256M
reservations:
cpus: '0.25'
memory: 128M
Advanced Configuration (Optional)
Drain a Node for Maintenance
# Prevent scheduling on a node
docker node update --availability drain node-2
# Bring it back
docker node update --availability active node-2
Placement Constraints
Control where services run:
deploy:
placement:
constraints:
- node.role == worker
- node.labels.disk == ssd
Add labels to nodes:
docker node update --label-add disk=ssd node-2
Global Services
Run one instance per node (useful for monitoring agents):
deploy:
mode: global
Backup
Back up the Swarm state:
# On a manager node — back up the Swarm Raft data
sudo cp -r /var/lib/docker/swarm/raft ./swarm-backup
# Also back up secrets and configs
docker secret ls
docker config ls
For application data, back up the volumes used by your services. See Backup Strategy.
Troubleshooting
Service Replicas Stuck at 0/N
Symptom: docker service ls shows 0 running replicas.
Fix: Check service logs:
docker service logs web
docker service ps web --no-trunc
Common causes: image pull failures, port conflicts, or placement constraints that no node satisfies.
Nodes Not Joining the Cluster
Symptom: Worker node join command hangs or fails.
Fix: Verify port connectivity between nodes:
# From worker, test manager port
nc -zv <MANAGER-IP> 2377
Ensure ports 2377, 7946, and 4789 are open in firewalls on all nodes.
Overlay Network Connectivity Issues
Symptom: Services on the same overlay network can’t reach each other.
Fix: Check that UDP port 4789 is open between all nodes. Some cloud providers block VXLAN traffic by default. Also verify the overlay network is attached to both services.
Manager Node Lost Quorum
Symptom: docker node ls fails with “Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader.”
Fix: If the majority of managers are down, you need to force a new cluster:
docker swarm init --force-new-cluster --advertise-addr <IP>
This recovers from the current node’s Raft state. Re-join other nodes afterward.
Resource Requirements
- RAM: 512 MB per node minimum, plus your workload requirements
- CPU: 1 core per node minimum
- Disk: Minimal overhead — Docker Swarm adds negligible storage beyond standard Docker
- Network: Reliable connectivity between all nodes. Low latency between managers is important.
Verdict
Docker Swarm is the simplest container orchestrator. If you already use Docker Compose and want to scale to multiple nodes without learning Kubernetes, Swarm is the natural next step — same Docker CLI, same Compose files (with a deploy section), zero new tools to install.
Use Docker Swarm if: You want simple multi-node container orchestration, you already know Docker well, and you don’t need the full Kubernetes ecosystem (Helm charts, operators, CRDs).
Consider k3s instead if: You want access to the Kubernetes ecosystem (Helm, operators, community manifests) or you’re planning to scale beyond a handful of nodes. See Docker Swarm vs Kubernetes.
FAQ
Is Docker Swarm dead?
No. Docker continues to maintain Swarm mode. It receives updates with each Docker release. However, it’s not getting major new features — Docker’s orchestration focus has shifted to Kubernetes support.
Can I use Docker Compose files with Swarm?
Yes. docker stack deploy -c docker-compose.yml deploys Compose files to Swarm. The deploy section in the Compose file controls Swarm-specific settings (replicas, update policy, placement).
How many manager nodes do I need?
One manager works for testing. For production, use 3 (tolerates 1 failure) or 5 (tolerates 2 failures). Never use an even number — Raft consensus needs an odd count.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments