Chapter 67: Docker Swarm vs Kubernetes: the Same App on Both, Side by Side
67.1 Docker Swarm from zero: managers, workers, Raft and your first service
Why: the problem
Before we can compare Swarm and Kubernetes fairly, we need a real Swarm in front of us. Docker Swarm mode is the orchestrator built into Docker Engine itself. There is nothing extra to install: the same docker binary that runs containers on your laptop can turn a group of machines into one cluster with a single command, docker swarm init. That simplicity is the main reason teams still pick it, and it is also why it is the best place to start the comparison. Why does an orchestrator exist at all? Running one container with docker run is easy. Running twelve copies across three servers, replacing the ones that die, spreading them across machines, giving them one stable address and updating them without downtime is not something a human should do by hand at 2 AM. An orchestrator keeps a desired state, such as "six replicas of orders:1.0.0 on port 8080", and works all the time to make the real state match it. Kubernetes does this with controllers and etcd; Swarm does it with managers that share a Raft log. What is inside a Swarm? Manager nodes accept commands, store the cluster state in a replicated Raft database and schedule tasks. Worker nodes only run tasks. A service is the desired state you declare, and each running container of a service is a task. Swarm creates an overlay network so containers on different machines talk as if they were on one LAN, and its routing mesh publishes a port on every node so a request to any node reaches a healthy task. Managers need a majority, called quorum, to make changes: three managers survive one failure, five survive two. This is the same rule etcd follows in Kubernetes. How will we build it? On a laptop we do not have three servers, so we run three Docker-in-Docker containers as nodes on one bridge network, exactly as many training labs and CI systems do. If you have three EC2 instances, the commands are identical; you only open ports 2377/tcp for management, 7946/tcp and udp for node gossip and 4789/udp for overlay traffic. We initialise the first manager, join two more nodes with tokens, inspect the cluster, run a first service with three replicas, and watch Swarm heal it when we remove a container by force.
What: every term in plain English
- Swarm mode — Orchestrator built into Docker Engine, enabled with docker swarm init.
- Manager node — Stores cluster state in Raft and schedules tasks; can also run tasks.
- Worker node — Only runs tasks given by managers.
- Raft — Consensus algorithm managers use to agree on cluster state.
- Quorum — Majority of managers, such as 2 of 3, needed to change state.
- Join token — Secret string that lets a node join as a worker or a manager.
- Service — Desired state: image, replicas, ports, networks, update policy.
- Task — One container scheduled for a service on a node.
- Overlay network — Virtual network spanning all nodes, encrypted on request.
- Routing mesh — Publishes a service port on every node and forwards to healthy tasks.
How: step by step
- Create a bridge network for the lab nodes. Nodes can reach each other.
- Start three docker:dind containers as nodes. Three engines.
- Run docker swarm init on node1. First manager.
- Read the worker and manager join tokens. Tokens printed.
- Join node2 as manager and node3 as worker. Three nodes.
- List nodes and check quorum. Leader and reachable managers.
- Create a service with three replicas. Tasks spread out.
- Remove a task container by force and watch healing. Replaced in seconds.
A useful way to remember the architecture is to map every Swarm part to its Kubernetes partner before we go further. Swarm managers with their Raft store play the role of the API server, etcd, scheduler and controller manager combined into one process. Swarm workers play the role of kubelet nodes. A Swarm service is close to a Deployment plus a Service in one object, and a task is close to a pod with one container. The routing mesh is close to a NodePort Service with kube-proxy on every node. Keeping this map in mind makes the next three lessons much easier, because you will see the same idea twice with different names. Notice also what is missing in Swarm: there is no separate CNI choice, no admission controllers, no custom resources and no operators. Fewer moving parts make Swarm easy to learn and operate; the same missing parts are exactly what large platforms at Flipkart, Swiggy or Zomato rely on in Kubernetes.
Example 1: Build a three-node Swarm on one laptop
Goal. Build a three-node Swarm on one laptop.
nodes.sh
docker network create swarmlab
for n in node1 node2 node3; do
docker run -d --privileged --name $n --hostname $n --network swarmlab docker:28-dind
done
sleep 8
alias d1='docker exec node1 docker'
docker exec node1 docker swarm init --advertise-addr eth0
WTOKEN=$(docker exec node1 docker swarm join-token -q worker)
MTOKEN=$(docker exec node1 docker swarm join-token -q manager)
docker exec node2 docker swarm join --token $MTOKEN node1:2377
docker exec node3 docker swarm join --token $WTOKEN node1:2377
docker exec node1 docker node ls
What each line does
docker:28-dind— Docker-in-Docker image; each container is a full Docker Engine acting as a node.--privileged— Needed only for this lab so the inner engine can create containers; never use it for app containers.swarm init --advertise-addr— Tells other nodes which address reaches this manager.join-token -q— Prints only the token, so we can store it in a variable instead of copying by hand.node2 as manager— Two managers are not fault tolerant yet; we add a third in the next example.
Green output
$ bash nodes.sh
Swarm initialized: current node (k3x9...) is now a manager.
This node joined a swarm as a manager.
This node joined a swarm as a worker.
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
k3x9q1... * node1 Ready Active Leader 28.5.1
p7m2w8... node2 Ready Active Reachable 28.5.1
z4c6v0... node3 Ready Active 28.5.1
Expected result. One command created the cluster and two more joined the nodes. Compare this with Kubernetes, where even kind needs a config file and kubeadm needs certificates, a CNI and a join command per node.
Example 2: Quorum in practice: promote, demote and lose a manager
Goal. Quorum in practice: promote, demote and lose a manager.
quorum.sh
docker exec node1 docker node promote node3
docker exec node1 docker node ls --format '{{.Hostname}} {{.ManagerStatus}}'
docker stop node2
sleep 5
docker exec node1 docker node ls --format '{{.Hostname}} {{.Status}} {{.ManagerStatus}}'
docker exec node1 docker service ls
docker stop node3
sleep 5
docker exec node1 docker service ls || true
docker start node2 node3
sleep 10
docker exec node1 docker node ls --format '{{.Hostname}} {{.Status}} {{.ManagerStatus}}'
What each line does
docker node promote— Turns a worker into a manager; now we have three managers.Stop node2— One of three managers is gone; 2 of 3 is still a majority, so the cluster works.Stop node3 too— Only 1 of 3 left, no quorum, so management commands fail while running tasks keep serving.Start them again— Managers rejoin and Raft catches them up automatically.--format— Go template output keeps the screen readable.
Green output
$ bash quorum.sh
Node node3 promoted to a manager in the swarm.
node1 Leader
node2 Reachable
node3 Reachable
node1 Ready Leader
node2 Down Unreachable
node3 Ready Reachable
ID NAME MODE REPLICAS IMAGE PORTS
Error response from daemon: rpc error: code = Unknown desc = The swarm does not have a leader. It's possible that too few managers are online.
node1 Ready Leader
node2 Ready Reachable
node3 Ready Reachable
Expected result. Three managers survive one failure, never two. This is exactly the etcd rule in Kubernetes, which is why both production Swarms and production control planes use three or five managers, never two or four.
Example 3: First service: replicas, routing mesh and self-healing
Goal. First service: replicas, routing mesh and self-healing.
service.sh
docker exec node1 docker service create --name web --replicas 3 --publish 8080:80 nginx:1.27-alpine
docker exec node1 docker service ps web --format '{{.Name}} {{.Node}} {{.CurrentState}}'
docker exec node3 wget -qO- http://node1:8080 | grep -o '<title>.*</title>'
TASK=$(docker exec node2 docker ps -q --filter name=web | head -1)
docker exec node2 docker rm -f $TASK
sleep 4
docker exec node1 docker service ps web --format '{{.Name}} {{.Node}} {{.CurrentState}} {{.Error}}'
docker exec node1 docker service scale web=6
docker exec node1 docker service ls
What each line does
service create— Declares desired state: three replicas of nginx with port 8080 published.service ps— Shows each task, its node and state; tasks are spread across nodes.Routing mesh— node3 calls node1:8080 and gets an answer even if no web task runs on node1.docker rm -f— Simulates a crash; the manager sees fewer running tasks than desired.service scale— Changes desired replicas, like kubectl scale.
Green output
$ bash service.sh
web
overall progress: 3 out of 3 tasks
verify: Service web converged
web.1 node1 Running 5 seconds ago
web.2 node2 Running 5 seconds ago
web.3 node3 Running 5 seconds ago
<title>Welcome to nginx!</title>
web.2 node2 Running 3 seconds ago
\_ web.2 node2 Failed 4 seconds ago task: non-zero exit (137)
web scaled to 6
ID NAME MODE REPLICAS IMAGE PORTS
x1y2 web replicated 6/6 nginx:1.27-alpine *:8080->80/tcp
Expected result. Swarm replaced the killed task in about four seconds and keeps the failed one in history. The Kubernetes equivalent is a ReplicaSet recreating a deleted pod, which you saw in Chapter 60.
Every command, step by step (kind lab with kubectl)
-
Network
docker network create swarmlabWhat it does: Lab LAN.
3c1f... -
Nodes
docker run -d --privileged --name node1 --network swarmlab docker:28-dindWhat it does: Engine.
9a8b... -
Init
docker exec node1 docker swarm init --advertise-addr eth0What it does: Manager.
Swarm initialized -
Token
docker exec node1 docker swarm join-token -q workerWhat it does: Worker token.
SWMTKN-1-xxxx -
Join
docker exec node3 docker swarm join --token $WTOKEN node1:2377What it does: Worker.
This node joined a swarm as a worker. -
Nodes
docker exec node1 docker node lsWhat it does: Cluster.
node1 Leader -
Promote
docker exec node1 docker node promote node3What it does: Third manager.
promoted -
Service
docker exec node1 docker service create --name web --replicas 3 -p 8080:80 nginx:1.27-alpineWhat it does: Deploy.
converged -
Tasks
docker exec node1 docker service ps webWhat it does: Placement.
web.1 node1 Running -
Scale
docker exec node1 docker service scale web=6What it does: Six.
web scaled to 6
When it is red 1
Error response from daemon: This node is not a swarm manager.
Cause. Running a service command on a worker.
Fix, step by step
- Run it on a manager, or promote the node.
When it is red 2
Timeout was reached before node joined.
Cause. Port 2377 blocked between nodes.
Fix, step by step
- Open 2377/tcp, 7946/tcp+udp, 4789/udp in the security group.
When it is red 3
The swarm does not have a leader.
Cause. Quorum lost.
Fix, step by step
- Bring managers back, or run docker swarm init --force-new-cluster on one survivor.
When it is red 4
service web: 0/3 replicas, no suitable node
Cause. Constraints or resources cannot be met.
Fix, step by step
- docker service ps web --no-trunc to read the reason.
When it is red 5
curl to the published port hangs
Cause. Overlay ports blocked or the task is unhealthy.
Fix, step by step
- Check 4789/udp and docker service ps.
Practice tasks
Easy Task 1: Init
Why: Start.
What to do: Run docker swarm init.
- Leader shown.
Solution
docker node lsEasy Task 2: Join
Why: Nodes.
What to do: Join a worker.
- Use join-token -q.
Solution
docker node lsEasy Task 3: Service
Why: Deploy.
What to do: Create nginx with 3 replicas.
- Publish 8080.
Solution
docker service lsMedium Task 4: Spread
Why: Placement.
What to do: Check which node runs each task.
- service ps.
Solution
docker service ps webMedium Task 5: Heal
Why: Crash.
What to do: Force-remove a task container.
- Watch history.
Solution
docker service ps webMedium Task 6: Quorum
Why: Managers.
What to do: Promote to three managers and stop one.
- Still works.
Solution
docker service lsHard Task 7: Lose
Why: Two down.
What to do: Stop two managers.
- Read the error.
Solution
docker service lsHard Task 8: Dunzo
Why: Main task.
What to do: Tracker Swarm with timings.
- 4/4 again.
Solution
docker service lsHomework: try at home
For Dunzo's delivery tracker, build a three-manager plus one-worker Swarm, run nginx with four replicas on port 8081, kill one manager and one task, and record how long the service takes to return to 4/4.
Recap
- Swarm mode is built into Docker; docker swarm init creates a cluster.
- Managers keep state with Raft and need a majority, so run three or five.
- A service is desired state; each container is a task.
- The routing mesh publishes a port on every node.
- Swarm heals failed tasks automatically, like a Kubernetes ReplicaSet.
FAQ
Q. Is Docker Swarm dead?
No. Mirantis maintains Swarm mode in Docker Engine and supports it commercially, with a long-term support commitment, but new features are rare and the community is far smaller than Kubernetes.
Q. Is Swarm the same as classic Docker Swarm?
No. Classic Swarm was a separate project and is retired. Everything here is Swarm mode, built into Docker Engine since 1.12.
Q. Can managers run app tasks?
Yes, by default. In production you can drain managers with docker node update --availability drain so they only manage.
Q. Can I run this lab on EC2 instead of Docker-in-Docker?
Yes. Launch three t3.small Amazon Linux 2023 instances in one VPC subnet, install Docker with dnf, allow 2377/tcp, 7946/tcp and udp and 4789/udp between them in one security group, and run the same init and join commands with each private IP as the advertise address. Everything else in this chapter stays the same, and the routing mesh then answers on every public IP.
Q. Is the overlay network encrypted?
Control traffic is always encrypted with TLS. Add --opt encrypted to an overlay network to encrypt app traffic too.
Interview questions
-
What is the difference between a manager and a worker?
Model answer: Managers hold Raft state and schedule; workers only run tasks.
-
Why an odd number of managers?
Model answer: Quorum needs a majority; four managers tolerate only one failure, the same as three.
-
How does Swarm self-heal?
Model answer: Managers compare running tasks with desired replicas and schedule replacements.
-
What ports must be open for Swarm?
Model answer: 2377/tcp, 7946/tcp and udp, and 4789/udp.
Quick quiz
Q1. Which port do managers use?
2377/tcp.
Q2. How many managers survive one failure?
Three.
Q3. What is a task?
One container of a service.
Q4. What does the routing mesh do?
Publishes the port on every node.
Q5. Which command adds desired replicas?
docker service scale.
Samajla ka?