Skip to main content

Docker Swarm: Multi-VPS Cluster Without Kubernetes

Cloud & DevOps · 19.04.2026 · 5 min read
Illustration for “Docker Swarm: Multi-VPS Cluster Without Kubernetes”

Docker Swarm: A Cluster for Small Teams

Docker Swarm is the orchestration tool built into Docker. Unlike Kubernetes, it is far simpler to set up and fits projects with 2-10 servers.

Initializing the Cluster

# Manager node
docker swarm init --advertise-addr 10.0.0.1

# Worker node
docker swarm join --token SWMTKN-1-xxxxx 10.0.0.1:2377

docker node ls

Deploy Stack

# docker-stack.yml
version: '3.8'
services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
    networks:
      - webnet

  app:
    image: myapp:latest
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
    networks:
      - webnet

networks:
  webnet:
    driver: overlay
docker stack deploy -c docker-stack.yml myapp
docker stack services myapp
docker service ps myapp_web

Secrets

echo "SuperSecretPass" | docker secret create db_password -
docker secret ls

Rolling Update With No Downtime

docker service update --image myapp:v2.0 --update-parallelism 1 --update-delay 15s myapp_app
docker service rollback myapp_app  # rollback

Scaling

docker service scale myapp_web=5 myapp_app=4
Swarm vs K8s? Swarm is the right choice for 2–20 servers and teams without a DevOps engineer. Kubernetes pays off at 20+ nodes.

Common Deployment Errors

Most Docker Swarm problems come down to three causes: closed ports between nodes, insufficient resources for replicas, and confusion about node roles (manager versus worker). Below are the typical error messages an administrator sees in the console during the first deployment, and what is really going on behind each one.

A Worker Cannot Join the Cluster

Error response from daemon: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp 10.0.0.1:2377: i/o timeout"

This means traffic cannot pass between the manager and the worker. Swarm uses three ports: 2377/tcp (cluster management), 7946/tcp and 7946/udp (state exchange between nodes), and 4789/udp (the VXLAN overlay network). Open them in the firewall on both nodes and retry docker swarm join.

The Command Only Works on the Manager Node

Error response from daemon: This node is not a swarm manager. Use "docker swarm init" or "docker swarm join" to connect this node to swarm and try again.

The docker service, docker stack, and docker node commands only work on manager nodes. If you connected via SSH to a worker and got this error, that is expected — log in to the manager node instead.

A Task Keeps Restarting

ID          NAME       IMAGE          NODE      DESIRED STATE   CURRENT STATE
abc123      web.1      myapp:latest   node-2    Running         Running 5 seconds ago
xyz789       \_ web.1   myapp:latest   node-2    Shutdown        Failed 2 minutes ago "task: non-zero exit (1)"

The line non-zero exit (1) means the process inside the container exited with an error right after startup — that is an application problem, not a Swarm problem. Check docker service logs: the usual cause is a missing environment variable, a database that is unreachable at startup, or the wrong CMD in the image. Swarm will keep restarting that task forever until the underlying cause is fixed.

Docker Swarm vs. Alternatives

Choosing an orchestrator usually comes down not to "which is better" but to team size and the project's growth horizon. Here is a comparison by the criteria that actually drive the decision.

CriterionDocker Swarmk3s (Kubernetes)Nomad
Learning curveLow — Docker Compose knowledge is enoughHigh — its own set of concepts and YAMLMedium
Minimum RAM per node512 MB512 MB256 MB
Self-healing tasksBuilt inYes, more flexible configurationYes
Ecosystem of ready-made chartsNoneThousands of Helm chartsLimited

When Docker Swarm Is Not a Good Fit

Swarm honestly solves the problems of small and mid-sized teams, but it has a ceiling — here are five signs it is time to look at Kubernetes instead.

  • You need Kubernetes-specific resources — CRDs, Operators, StatefulSets with advanced volume management.
  • The cluster needs to grow beyond 20-30 nodes — Swarm was not designed for that scale, and its monitoring ecosystem is weaker.
  • Your team already knows Kubernetes and needs manifest portability across cloud providers.
  • You need a built-in service mesh with mTLS between services out of the box — in Swarm you would have to build that yourself.
  • You need automatic horizontal scaling based on load metrics — in Swarm scaling is manual only, via docker service scale.

Verifying the Cluster After Deployment

# All nodes should be Ready and Active
docker node ls

# All service replicas are in the Running state
docker service ps myapp_web --no-trunc

# An HTTP response through any node — the overlay network balances requests itself
curl -I http://localhost/

# Logs for a specific task on failure
docker service logs myapp_web --tail 50

If the CURRENT STATE column shows Failed or Rejected, the service did not come up. Check the task logs and review the limits in deploy.resources.limits: the usual cause is that the requested memory does not fit on any node. Connect the finished cluster to monitoring with Uptime Kuma right away so you can see replica failures, and set up volume backups with rclone.

Was this article helpful?
← Back to Knowledge Base Ask Support