Ravindra BagaleCourses & study guides मराठी

Chapter 67: Docker Swarm vs Kubernetes: the Same App on Both, Side by Side

67.2 Deploy the orders app on Swarm: stack file, secrets, health checks, scaling and rolling updates

Why: the problem

Now we put a real app on the Swarm: the orders API from Chapter 66 plus a Postgres database. On Swarm the unit of deployment is a stack, a group of services, networks, volumes, configs and secrets described in one Compose file and deployed with docker stack deploy. If your team already uses docker compose on laptops, this is the shortest road to a cluster, because the file format is almost the same. That is Swarm's biggest selling point, and the reason small teams at agencies and startups still reach for it. Why a stack and not a list of docker service create commands? For the same reason we write Kubernetes YAML instead of typing kubectl run: a file can be reviewed in a pull request, stored in Git and applied again after a disaster. docker stack deploy is idempotent, so running it twice changes nothing, and changing one line in the file updates only the service that changed. What goes into the file? The deploy key is where Swarm lives. It sets replicas, the update_config for rolling updates (parallelism, delay, failure_action and order start-first for zero downtime), a rollback_config, restart_policy, resource limits and reservations, and placement constraints such as node.role == worker. Swarm secrets are encrypted in the Raft log and mounted as files under /run/secrets inside only the services that ask for them, so the database password never appears in an environment listing. A healthcheck tells Swarm when a task is healthy; during an update Swarm waits for health before moving on. How will we run it? We create a secret from the command line with a placeholder value, write the stack file with printf, push the image to a registry every node can reach, deploy, scale to six, roll out version 1.1.0 with start-first ordering while a loop calls the API, break an update on purpose to watch the automatic rollback, and roll back by hand. Every step has a direct Kubernetes twin in the next lesson, so keep your timings: you will compare them in 67.4.

What: every term in plain English

  • Stack — Group of services, networks, volumes and secrets deployed from one Compose file.
  • docker stack deploy — Creates or updates every object in a stack; safe to run repeatedly.
  • deploy.replicas — Desired number of tasks for a service.
  • update_config — Rolling update settings: parallelism, delay, order, failure_action, monitor.
  • order: start-first — Start the new task before stopping the old one, for zero downtime.
  • rollback_config — How Swarm rolls back when an update fails.
  • Swarm secret — Encrypted value mounted as a file in /run/secrets.
  • Swarm config — Non-secret file distributed to services, like a ConfigMap.
  • healthcheck — Command Swarm runs to decide if a task is healthy.
  • Placement constraint — Rule such as node.role == worker that limits where tasks run.
Start a local registry as a Swarm service. Push orders 1.0.0, 1.1.0 and a broken 1.2.0. Create the db_password secret. Write stack.yml with printf. Deploy the stack. Call the API through the routing mesh. Scale orders to six.
A Swarm stack: orders, Postgres and a secret

How: step by step

  1. Start a local registry as a Swarm service. Nodes can pull.
  2. Push orders 1.0.0, 1.1.0 and a broken 1.2.0. Three versions.
  3. Create the db_password secret. Encrypted in Raft.
  4. Write stack.yml with printf. One file.
  5. Deploy the stack. Services converge.
  6. Call the API through the routing mesh. Orders returned.
  7. Scale orders to six. Six tasks.
  8. Roll out 1.1.0 while traffic runs. No failed requests.
  9. Roll out broken 1.2.0 and watch rollback. Back to 1.1.0.
  10. Remove the stack. Clean.

Pay attention to how much behaviour is packed into a few lines of the deploy key, because this is where the two tools differ most in philosophy. Swarm gives you sensible defaults and a small number of knobs: you can say how many tasks update at once, how long to wait, which order to use and what to do on failure. Kubernetes splits the same ideas into maxSurge, maxUnavailable, readiness probes, minReadySeconds, progressDeadlineSeconds and a separate rollback command, and lets tools like Argo Rollouts replace the whole strategy. For a ten-person team running a dozen services, the Swarm version is often enough and much easier to explain to a new hire. For a company like Swiggy shipping hundreds of services with canaries and automated analysis, the extra knobs are the point.

Example 1: Registry, images and secret

Goal. Registry, images and secret.

prep.sh

M='docker exec node1 docker'
$M service create --name registry --publish 5000:5000 registry:2
for v in 1.0.0 1.1.0 1.2.0-broken; do
  docker exec node1 sh -c "printf 'FROM nginx:1.27-alpine\\nRUN echo $v > /usr/share/nginx/html/version\\n' | docker build -t 127.0.0.1:5000/orders:$v -"
  $M push 127.0.0.1:5000/orders:$v
done
printf '%s' 'REPLACE_WITH_DB_PASSWORD' | docker exec -i node1 docker secret create db_password -
$M secret ls
$M secret inspect db_password --format '{{.Spec.Name}} {{.CreatedAt}}'

What each line does

  • registry service — Every node reaches it at 127.0.0.1:5000 through the routing mesh, so all nodes can pull.
  • Three tags — A good release, a newer release and one we break on purpose; in real life use the orders image from Chapter 66.
  • docker secret create - — Reads the value from stdin, so it never appears in shell history; the value here is a placeholder.
  • secret inspect — Shows metadata only; Swarm never prints a secret value back.
  • Raft encryption — Secrets are stored encrypted on managers and sent only to nodes running a service that uses them.

Green output

$ bash prep.sh
registry
overall progress: 1 out of 1 tasks
The push refers to repository [127.0.0.1:5000/orders]
1.0.0: digest: sha256:1a2b... size: 1568
1.1.0: digest: sha256:3c4d... size: 1568
1.2.0-broken: digest: sha256:5e6f... size: 1568
ID          NAME          CREATED
q8r7...     db_password   2 seconds ago
db_password 2026-10-25 03:10:41 +0000 UTC

Expected result. The cluster now has a registry, three image versions and an encrypted secret. Notice that nothing printed the password.

Example 2: The stack file and the first deploy

Goal. The stack file and the first deploy.

stack.sh

mkdir -p swarm
printf '%s\n' \
 'services:' \
 '  orders:' \
 '    image: 127.0.0.1:5000/orders:1.0.0' \
 '    ports: ["8080:80"]' \
 '    networks: [backend]' \
 '    secrets: [db_password]' \
 '    environment: {DB_HOST: db, DB_PASSWORD_FILE: /run/secrets/db_password}' \
 '    healthcheck: {test: ["CMD", "wget", "-qO-", "http://127.0.0.1/version"], interval: 5s, retries: 3}' \
 '    deploy:' \
 '      replicas: 3' \
 '      resources: {limits: {cpus: "0.50", memory: 128M}, reservations: {memory: 64M}}' \
 '      update_config: {parallelism: 1, delay: 5s, order: start-first, failure_action: rollback, monitor: 15s}' \
 '      rollback_config: {parallelism: 2, order: start-first}' \
 '      restart_policy: {condition: on-failure, max_attempts: 3}' \
 '  db:' \
 '    image: postgres:17-alpine' \
 '    networks: [backend]' \
 '    secrets: [db_password]' \
 '    environment: {POSTGRES_PASSWORD_FILE: /run/secrets/db_password}' \
 '    volumes: [dbdata:/var/lib/postgresql/data]' \
 '    deploy: {replicas: 1, placement: {constraints: [node.hostname == node3]}}' \
 'networks: {backend: {driver: overlay}}' \
 'volumes: {dbdata: {}}' \
 'secrets: {db_password: {external: true}}' > swarm/stack.yml
docker cp swarm/stack.yml node1:/stack.yml
docker exec node1 docker stack deploy -c /stack.yml shop
sleep 15
docker exec node1 docker stack services shop
docker exec node2 wget -qO- http://127.0.0.1:8080/version

What each line does

  • Compose format — The same file style as docker compose; the deploy key is what Swarm adds.
  • POSTGRES_PASSWORD_FILE — The official Postgres image reads the password from the secret file, not from an env value.
  • order: start-first — New task starts and becomes healthy before an old one stops.
  • failure_action: rollback — If new tasks fail health within monitor time, Swarm rolls back by itself.
  • placement constraint — Pins the database to node3, because its local volume lives there; this is Swarm's weak spot for storage.

Green output

$ bash stack.sh
Creating network shop_backend
Creating service shop_db
Creating service shop_orders
ID     NAME         MODE        REPLICAS  IMAGE                        PORTS
a1..   shop_db      replicated  1/1       postgres:17-alpine
b2..   shop_orders  replicated  3/3       127.0.0.1:5000/orders:1.0.0  *:8080->80/tcp
1.0.0

Expected result. One file and one command created a network, two services, a volume and wired in the secret. A Kubernetes version of this needs a Deployment, a Service, a StatefulSet, a Secret and a PVC: more objects, but each can be tuned on its own.

Example 3: Scale, rolling update under load, automatic rollback

Goal. Scale, rolling update under load, automatic rollback.

ops.sh

M='docker exec node1 docker'
$M service scale shop_orders=6
docker exec -d node3 sh -c 'while true; do wget -qO- http://127.0.0.1:8080/version >> /tmp/hits || echo FAIL >> /tmp/hits; sleep 0.2; done'
time $M service update --image 127.0.0.1:5000/orders:1.1.0 shop_orders
docker exec node3 sh -c 'sort /tmp/hits | uniq -c'
$M service update --image 127.0.0.1:5000/orders:1.2.0-broken \
  --health-cmd 'wget -qO- http://127.0.0.1/missing' shop_orders || true
$M service inspect shop_orders --format '{{.Spec.TaskTemplate.ContainerSpec.Image}} {{.UpdateStatus.State}}'
$M service rollback shop_orders
$M stack rm shop

What each line does

  • service scale — Six tasks across three nodes in a few seconds.
  • Traffic loop — Calls the API five times a second during the update and logs any failure.
  • time — Records rollout time for six tasks with parallelism 1 and a 5 second delay.
  • Broken health check — New tasks never get healthy, so failure_action rollback fires.
  • service rollback — Manual rollback to the previous spec, like kubectl rollout undo.

Green output

$ bash ops.sh
shop_orders scaled to 6
overall progress: 6 out of 6 tasks
verify: Service shop_orders converged
real    0m58.4s
    212 1.0.0
    287 1.1.0
rollback: update rolled back due to failure or early termination of task 7kq...
127.0.0.1:5000/orders:1.1.0 rollback_completed
shop_orders
rollback: manually requested rollback
Removing service shop_db
Removing service shop_orders
Removing network shop_backend

Expected result. Zero FAIL lines during the update, an automatic rollback when the broken release could not pass health, and a manual rollback with one command. Note the 58 second rollout time; we will compare it with Kubernetes.

Every command, step by step (kind lab with kubectl)

  1. Registry

    docker service create --name registry -p 5000:5000 registry:2
    

    What it does: Images.

    registry
    
  2. Push

    docker push 127.0.0.1:5000/orders:1.0.0
    

    What it does: Image.

    digest: sha256:1a2b...
    
  3. Secret

    printf '%s' 'REPLACE_WITH_DB_PASSWORD' | docker secret create db_password -
    

    What it does: Encrypted.

    q8r7...
    
  4. Deploy

    docker stack deploy -c stack.yml shop
    

    What it does: Stack.

    Creating service shop_orders
    
  5. Services

    docker stack services shop
    

    What it does: Status.

    shop_orders 3/3
    
  6. Tasks

    docker stack ps shop
    

    What it does: Placement.

    shop_orders.1 node1 Running
    
  7. Scale

    docker service scale shop_orders=6
    

    What it does: Six.

    scaled to 6
    
  8. Update

    docker service update --image 127.0.0.1:5000/orders:1.1.0 shop_orders
    

    What it does: Rolling.

    converged
    
  9. Rollback

    docker service rollback shop_orders
    

    What it does: Undo.

    rollback: manually requested rollback
    
  10. Remove

    docker stack rm shop
    

    What it does: Clean.

    Removing network shop_backend
    

When it is red 1

No such image: 127.0.0.1:5000/orders:1.0.0

Cause. Image not in a registry every node can reach.

Fix, step by step

  1. Push to a registry; Swarm nodes do not share local images.

When it is red 2

secret not found: db_password

Cause. External secret not created before deploy.

Fix, step by step

  1. docker secret create db_password - first.

When it is red 3

shop_db 0/1: no suitable node (scheduling constraints not satisfied)

Cause. Constraint points at a missing node.

Fix, step by step

  1. Fix node.hostname or add a label with docker node update --label-add.

When it is red 4

update paused due to failure

Cause. failure_action is pause.

Fix, step by step

  1. Set failure_action: rollback or run docker service update --rollback.

When it is red 5

Ignoring unsupported options: build

Cause. Swarm cannot build images.

Fix, step by step

  1. Build and push in CI, then reference the image.

Practice tasks

Easy Task 1: Secret

Why: Create.

What to do: Create db_password from stdin.

How:
  1. Placeholder value.
Solution
docker secret ls

Easy Task 2: Stack

Why: Write.

What to do: Write stack.yml with printf.

How:
  1. deploy key.
Solution
cat swarm/stack.yml

Easy Task 3: Deploy

Why: Run.

What to do: Deploy the stack.

How:
  1. 3/3.
Solution
docker stack services shop

Medium Task 4: Scale

Why: Six.

What to do: Scale to six.

How:
  1. service scale.
Solution
docker service ls

Medium Task 5: Update

Why: Rolling.

What to do: Update to 1.1.0 under load.

How:
  1. No FAIL.
Solution
sort /tmp/hits | uniq -c

Medium Task 6: Rollback

Why: Auto.

What to do: Deploy the broken tag.

How:
  1. Rolled back.
Solution
docker service inspect shop_orders

Hard Task 7: Manual

Why: Undo.

What to do: Roll back by hand.

How:
  1. service rollback.
Solution
docker service ps shop_orders

Hard Task 8: Urban Company

Why: Main task.

What to do: Booking API stack.

How:
  1. Zero failures.
Solution
docker stack ps booking

Homework: try at home

For Urban Company's booking API, write a stack with the API (4 replicas, start-first updates, automatic rollback) and Postgres with a secret, deploy it on your Swarm, roll out a new tag under a traffic loop and prove zero failed requests.

Recap

  • A stack is a Compose file deployed to Swarm with docker stack deploy.
  • The deploy key holds replicas, resources, updates, rollback and placement.
  • Swarm secrets are encrypted in Raft and mounted under /run/secrets.
  • start-first updates plus health checks give zero-downtime rollouts.
  • Local volumes tie stateful services to one node; this is Swarm's weakest area.

FAQ

Q. Can I use the same compose file for docker compose and Swarm?

Mostly. docker compose ignores most of deploy, and Swarm ignores build, depends_on conditions and some other keys. Many teams keep one base file plus a small Swarm override.

Q. How do I store Postgres data safely on Swarm?

Use a volume plugin backed by network storage, such as a CSI or NFS driver, or keep the database outside the cluster on Amazon RDS. Pinning to a node is fine only for labs.

Q. Does Swarm have autoscaling?

No built-in autoscaler. You change replicas yourself or with an external script that reads metrics, unlike the Kubernetes HPA from Chapter 63.

Q. How do I rotate a secret?

Create db_password_v2, update the service with --secret-rm db_password --secret-add db_password_v2, then remove the old secret. Secrets are immutable.

Interview questions

  1. How does Swarm do zero-downtime deployments?

    Model answer: Rolling updates with start-first ordering and health checks, plus automatic rollback on failure.

  2. How are Swarm secrets protected?

    Model answer: Encrypted at rest in Raft, sent over mutual TLS only to nodes that need them, mounted in memory under /run/secrets.

  3. What is the difference between docker compose and docker stack deploy?

    Model answer: Compose runs on one host; stack deploy runs services across a Swarm.

  4. What is Swarm's biggest limitation?

    Model answer: Stateful storage and the small ecosystem: no operators, no built-in autoscaling, few managed offerings.

Quick quiz

Q1. Which command deploys a Compose file to Swarm?

docker stack deploy -c.

Q2. Where are secrets mounted?

/run/secrets.

Q3. Which order gives zero downtime?

start-first.

Q4. What triggers automatic rollback?

failure_action: rollback with failed health.

Q5. Can Swarm build images?

No.

Samajla ka?