Docker Swarm turns several Docker hosts into one cluster. You deploy services and stacks (using Compose files), and Swarm schedules containers across nodes, restarts them on failure, load-balances traffic and performs rolling updates. It’s built into Docker — no extra software — and much simpler than Kubernetes.

When Swarm makes sense

  • You already use Docker Compose and want redundancy across 2–10 servers.
  • You need rolling updates and automatic rescheduling, without Kubernetes’ complexity.

For a single server, plain Docker Compose is enough. For large, complex platforms, Kubernetes (k3s) has the bigger ecosystem.

Requirements

  • Docker installed on every node (guide).
  • Network connectivity between nodes — ideally a private network or VPN.
  • Ports between nodes only: 2377/tcp (cluster management), 7946/tcp+udp (node communication), 4789/udp (overlay network traffic).

1. Initialise the swarm

On the first manager node:

docker swarm init --advertise-addr 10.0.0.10

It prints a docker swarm join command with a worker token. To get tokens later:

docker swarm join-token worker
docker swarm join-token manager

2. Join nodes

On each other node:

docker swarm join --token SWMTKN-1-… 10.0.0.10:2377

On the manager:

docker node ls

Managers maintain cluster state using Raft consensus. Use 1 or 3 (or 5) managers — an odd number survives failures: 3 managers tolerate 1 failure. Managers can also run workloads.

3. Deploy a service

docker service create --name web --replicas 3 -p 80:80 nginx:stable
docker service ls
docker service ps web

The routing mesh makes port 80 available on every node; requests to any node reach one of the replicas.

4. Deploy a stack from a Compose file

stack.yml:

services:
  app:
    image: ghcr.io/example/app:1.4
    ports:
      - "8080:3000"
    environment:
      DATABASE_URL: postgres://app@db:5432/app
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        order: start-first
        failure_action: rollback
      restart_policy:
        condition: on-failure
    networks: [backend]

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets: [db_password]
    volumes:
      - db-data:/var/lib/postgresql/data
    deploy:
      placement:
        constraints: [node.labels.db == true]
    networks: [backend]

networks:
  backend:
    driver: overlay

volumes:
  db-data:

secrets:
  db_password:
    external: true
printf 'a-long-random-password' | docker secret create db_password -
docker node update --label-add db=true node-2
docker stack deploy -c stack.yml shop
docker stack services shop

Key points:

  • deploy: settings (replicas, update policy, placement) only apply in Swarm.
  • Overlay networks span all nodes; services reach each other by name.
  • Secrets are encrypted in the cluster and mounted as files in /run/secrets/.
  • Volumes are local to a node. That’s why the database is pinned to one node with a placement constraint. For shared storage across nodes, you need NFS, a distributed filesystem, or — usually better — keep stateful services on fixed nodes.
  • Swarm doesn’t build images; push them to a registry first.

5. Scale and update

docker service scale shop_app=5
docker service update --image ghcr.io/example/app:1.5 shop_app
docker service rollback shop_app
docker service logs -f shop_app

Updates roll out one task at a time per update_config; with failure_action: rollback, a failing update reverts automatically. Health checks in the image make this reliable — see Docker health checks.

6. Node maintenance

docker node update --availability drain node-3     # move tasks away
# …maintenance, reboot…
docker node update --availability active node-3

Ingress and TLS

Put a reverse proxy in front: Traefik works well with Swarm (it reads service labels), or run Nginx/Caddy on the published port. With the routing mesh, point DNS at one or more nodes (or a floating IP — see keepalived).

Security notes

  • Keep ports 2377/7946/4789 closed to the internet; allow them only between nodes.
  • Swarm encrypts management traffic; add --opt encrypted to overlay networks to encrypt application traffic between nodes.
  • Published ports bypass host firewalls like UFW, as with plain Docker.

Swarm vs Kubernetes

Swarm is easier to learn and operate, using familiar Compose files. Kubernetes offers more features, a vast ecosystem (Helm, operators) and more industry momentum. For small teams with modest needs, Swarm is a perfectly reasonable choice. See Kubernetes vs Docker Compose.

Several small KVM VPS nodes in the same location make a cost-effective Swarm cluster.

  • Docker
  • Docker Swarm
  • DevOps