Set Up Docker Swarm Cluster on VPS

Set Up Docker Swarm Cluster on VPS

July 2026 · 8 min read

Docker Swarm is a built-in container orchestration tool that manages multiple containers across several nodes from a single API. Add a new container or scale up a service replica count with one command, and Swarm automatically places containers on appropriate nodes. Compared to Kubernetes, Swarm is simpler and faster to set up, with less operational overhead — ideal for teams needing a straightforward cluster without the complexity of managing a massive distributed system.

Prepare Each VPS Node

Before initializing Swarm, install Docker on all servers and ensure network connectivity between them. SSH into the first manager node and install Docker:

sudo apt update
sudo apt install docker.io docker-compose -y
sudo usermod -aG docker $USER
newgrp docker

# Open firewall ports for Swarm
sudo ufw allow 2376/tcp
sudo ufw allow 2377/tcp
sudo ufw allow 7946/tcp
sudo ufw allow 7946/udp
sudo ufw allow 4789/udp

Initialize Docker Swarm on the Manager Node

On the manager node (which will be the leader), initialize Swarm:

docker swarm init --advertise-addr=MANAGER_IP

# Output will show:
# Swarm initialized: current node (xxx) 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
#
# To add a manager to this swarm, run:
#     docker swarm join-token manager
Tip: Replace MANAGER_IP with the manager node's IP address that worker nodes can reach (not 127.0.0.1). If running multiple managers, use a floating IP or load balancer for high availability.

Join Worker Nodes to the Cluster

On each worker node, run the docker swarm join command from the previous step:

# SWMTKN-1-xxx is the token from the init step
docker swarm join --token SWMTKN-1-xxx MANAGER_IP:2377

# Success message: "This node joined a swarm as a worker."

To add additional manager nodes for high availability, first get the manager token:

# Run this on an existing manager node
docker swarm join-token manager

# Output provides the token for additional managers
docker swarm join --token SWMTKN-1-manager-xxx MANAGER_IP:2377

Create a Service from a Docker Image

Once the cluster is ready, create services using Docker images:

# Create a "web" service from nginx with 3 replicas
docker service create \
  --name web \
  --publish 80:80 \
  --replicas 3 \
  nginx:latest

# Scale the service to 5 replicas
docker service scale web=5

# View service logs
docker service logs web

# Remove the service
docker service rm web
Tip: Swarm distributes replicas automatically across worker nodes. Some nodes may host multiple replicas depending on available resources. Use the --constraint flag to restrict placement, such as --constraint node.hostname==worker-1.

Deploy a Stack from Docker Compose File

Instead of creating services individually, prepare a docker-compose.yml and deploy it as a stack:

version: '3.8'
services:
  web:
    image: nginx:latest
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
    ports:
      - "80:80"

  db:
    image: postgres:13
    deploy:
      replicas: 1
      placement:
        constraints: [node.role == manager]
    environment:
      POSTGRES_PASSWORD: secret123
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:

Deploy the stack on a manager node:

docker stack deploy -c docker-compose.yml myapp

# List all stacks
docker stack ls

# View services in the stack
docker stack services myapp

# View tasks (running container instances) in the stack
docker stack ps myapp

# Remove the stack
docker stack rm myapp

Set Up Overlay Network for Internal Communication

Overlay networks let containers on different nodes communicate over VXLAN. Control-plane traffic (gossip between managers) is automatically encrypted with AES-GCM, but data-plane traffic (your application's actual data) is not encrypted unless you create the network with the --opt encrypted flag:

# Create an overlay network with data-plane encryption
docker network create --driver overlay --opt encrypted --attachable mynet

# Use the network for a service
docker service create \
  --name myapp \
  --network mynet \
  --publish 8080:8080 \
  myapp:latest

# Services on mynet can reach each other via service name (DNS)
# e.g., ping myapp will reach a container in the myapp service

Verify That Docker Swarm Is Working Correctly

# Check cluster status
docker info | grep Swarm

# List all nodes
docker node ls

# Inspect a specific node
docker node inspect node-name

# List all services
docker service ls

# List tasks (containers) for a service
docker service ps web

# List overlay networks
docker network ls | grep overlay
Tip: If a node shows "Down" or "Drained" status, it may have issues. Use docker node update --availability drain node-name to prevent new containers from being scheduled on it. Existing containers will automatically migrate to other nodes, allowing you to repair the node offline.

Common Issues & Troubleshooting

Error: "node is not part of a swarm"

The node has not joined the Swarm cluster or has left it. Reinitialize as a manager with docker swarm init or join as a worker with docker swarm join:

# Check Swarm status
docker info | grep Swarm

# If inactive, initialize
docker swarm init --advertise-addr=LOCAL_IP

Error: "could not choose an IP address to advertise"

Docker cannot determine a usable IP address. Explicitly specify one during initialization:

# Find the interface IP
ip addr show

# Initialize with explicit IP
docker swarm init --advertise-addr=192.168.1.10

Error: "cannot accept new swarm requests" or "node is already part of a swarm"

The node is already in a Swarm or is standalone. Leave the current Swarm first:

# Leave the current Swarm
docker swarm leave --force

# Then join the new one
docker swarm join --token SWMTKN-1-xxx MANAGER_IP:2377

Error: "container status is not running"

A deployed service container failed to start. Check the service logs to diagnose:

docker service logs SERVICE_NAME --tail 50

# View tasks for the service
docker service ps SERVICE_NAME

# Check individual containers
docker ps -a
docker logs CONTAINER_ID

Error: "timeout when dialing" or manager node unresponsive

Network latency or firewall blocking Swarm ports. Ensure these ports are open:

# 2376/tcp - TLS port
# 2377/tcp - Manager communication
# 7946/tcp, 7946/udp - Node communication
# 4789/udp - Overlay network traffic

# Check firewall status
sudo ufw status numbered
# Open ports if needed
sudo ufw allow 2377/tcp
sudo ufw allow 7946/tcp
sudo ufw allow 7946/udp
sudo ufw allow 4789/udp

Frequently Asked Questions

How does Docker Swarm differ from Kubernetes?

Swarm is built into Docker and is simpler to set up with no extra software required. Kubernetes is more powerful with advanced features like auto-scaling, custom schedulers, and network policies, making it suitable for large production deployments. Swarm works well for teams managing hundreds to a few thousand containers without the operational complexity of Kubernetes.

Is the overlay network secure?

Overlay networks use VXLAN encapsulation. Control-plane traffic between manager nodes is automatically encrypted with AES-GCM, but application data-plane traffic is only encrypted if you create the network with --opt encrypted. Beyond that, security depends on proper network configuration — separate networks by stack and restrict communication between services to only what's necessary.

Can manager nodes run containers?

Yes, but it is not recommended. Manager nodes should focus on orchestration, not application workloads, to maintain cluster stability. If necessary, you can allow it with docker node update --availability active node-name, but best practice is to isolate application containers to worker nodes only.