← Back to DevBytes

When to Choose Docker Swarm Over Kubernetes

When to Choose Docker Swarm Over Kubernetes

Container orchestration has become a cornerstone of modern application deployment, and two names dominate the conversation: Kubernetes and Docker Swarm. While Kubernetes has captured the lion's share of attention and market adoption, Docker Swarm remains a powerful, lightweight alternative that is often the better choice for specific use cases. This tutorial explores when Docker Swarm is the right tool for the job, how to implement it, and the best practices that will keep your clusters healthy and maintainable.

What Is Docker Swarm?

Docker Swarm is Docker's native clustering and orchestration tool. It allows you to manage a cluster of Docker hosts as a single virtual system, exposing the same Docker API you already use for standalone containers. This means any tool that speaks to Docker — including the Docker CLI, Compose files, and CI/CD pipelines — can target a Swarm cluster with minimal changes.

A Swarm cluster consists of one or more manager nodes and worker nodes. Managers maintain cluster state, schedule services, and serve the Swarm API. Workers execute the containers assigned to them. Services in Swarm are declarative: you describe the desired state, and Swarm continuously reconciles reality to match it.

Why It Matters

Choosing the right orchestrator is not just a technical decision — it affects team velocity, operational overhead, infrastructure costs, and hiring. Kubernetes is a sprawling platform with hundreds of resources, a steep learning curve, and a rich ecosystem. Docker Swarm, by contrast, is intentionally minimal. It ships inside Docker itself, requires no additional installation, and can be learned in an afternoon.

For small teams, internal tools, edge deployments, and straightforward stateless services, the operational simplicity of Swarm can translate into faster shipping and lower maintenance burden. The question is not which tool is more powerful, but which tool fits the problem you actually have.

When Swarm Is the Better Choice

When Kubernetes Is the Better Choice

For balance, it is worth naming the scenarios where Kubernetes wins: large-scale multi-tenant platforms, complex networking and service mesh requirements, advanced autoscaling, custom controllers and operators, extensive third-party ecosystem integration, and organizations that have already invested in Kubernetes tooling and expertise. If any of these describe your situation, Swarm will likely become a limitation rather than a simplification.

Getting Started With Docker Swarm

Initializing a Swarm Cluster

Swarm mode is built into Docker. To create a single-node Swarm, run the following on your manager machine:

docker swarm init --advertise-addr <MANAGER_IP>

This command initializes the Swarm, makes the current node a manager, and prints a token that worker nodes can use to join. To add a worker node, run the printed command on each worker:

docker swarm join --token <WORKER_TOKEN> <MANAGER_IP>:2377

If you lose the token, you can retrieve it on a manager node:

docker swarm join-token worker

To promote a worker to a manager for high availability:

docker node promote <NODE_NAME>

Verifying Cluster State

List all nodes in the Swarm and inspect their roles and availability:

docker node ls

You should see output similar to:

ID                            HOSTNAME   STATUS    AVAILABILITY   MANAGER STATUS   ENGINE VERSION
abc123... *                   manager1   Ready     Active         Leader           24.0.7
def456...                     worker1    Ready     Active                          24.0.7
ghi789...                     worker2    Ready     Active                          24.0.7

Deploying Services

Creating a Service

The simplest way to deploy a workload in Swarm is to create a service directly from the CLI:

docker service create \
  --name web \
  --replicas 3 \
  --publish 8080:80 \
  nginx:alpine

This creates a service named web running three replicas of the nginx:alpine image, with port 80 inside the container published as port 8080 on every node in the Swarm. Swarm's routing mesh ensures that requests to any node on port 8080 are routed to a healthy replica.

Inspecting and Scaling Services

Check the status of your service:

docker service ps web

Scale the service up or down instantly:

docker service scale web=6

Update the image used by the service with a rolling update:

docker service update --image nginx:latest web

Using Docker Compose With Swarm Stacks

One of Swarm's greatest strengths is its compatibility with Docker Compose. You can take an existing Compose file and deploy it as a stack with a single command. This dramatically reduces the gap between local development and production.

Example Compose File

Create a file named stack.yml:

version: "3.8"

services:
  api:
    image: myregistry/api:1.0.0
    deploy:
      replicas: 4
      update_config:
        parallelism: 2
        delay: 10s
        failure_action: rollback
      restart_policy:
        condition: on-failure
        max_attempts: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
      placement:
        constraints:
          - node.role == worker
    networks:
      - appnet
    environment:
      - DATABASE_URL=postgres://db:5432/app

  db:
    image: postgres:15
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    volumes:
      - dbdata:/var/lib/postgresql/data
    networks:
      - appnet
    environment:
      - POSTGRES_PASSWORD=secretpassword
      - POSTGRES_DB=app

  visualizer:
    image: dockersamples/visualizer:stable
    ports:
      - "8080:8080"
    deploy:
      placement:
        constraints:
          - node.role == manager
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    networks:
      - appnet

networks:
  appnet:
    driver: overlay

volumes:
  dbdata:

Deploying the Stack

Deploy the stack to your Swarm:

docker stack deploy -c stack.yml myapp

List running stacks and their services:

docker stack ls
docker stack services myapp

Remove the stack when you no longer need it:

docker stack rm myapp

Networking and Service Discovery

Swarm provides built-in DNS-based service discovery. Every service is reachable by its service name from any container in the same overlay network. In the example above, the api service can connect to the database simply by using the hostname db. No additional configuration is required.

Overlay networks span all nodes in the Swarm and enable secure, encrypted communication between containers on different hosts. To create a custom overlay network:

docker network create --driver overlay --attachable mynet

The --attachable flag allows standalone containers to join the network, which is useful for debugging.

Secrets and Configs

Swarm includes native secrets management for sensitive data such as passwords, API keys, and TLS certificates. Secrets are encrypted at rest and in transit, and are only exposed to the services that explicitly reference them.

Creating and Using a Secret

Create a secret from a file or stdin:

echo "supersecret" | docker secret create db_password -

Reference the secret in your Compose file:

version: "3.8"

services:
  api:
    image: myregistry/api:1.0.0
    secrets:
      - db_password
    environment:
      - DB_PASSWORD_FILE=/run/secrets/db_password

secrets:
  db_password:
    external: true

Inside the container, the secret is mounted as a file at /run/secrets/db_password. Your application reads the file at startup to obtain the value. This approach keeps secrets out of environment variables and image layers.

Rolling Updates and Rollbacks

Swarm supports declarative rolling updates out of the box. When you update a service, Swarm gradually replaces old tasks with new ones according to the parameters you specify. The update_config section in the Compose file shown earlier controls parallelism, delay, and failure behavior.

To manually roll back to the previous version after a failed update:

docker service rollback web

You can also configure automatic rollback on failure by setting failure_action: rollback in the deploy configuration, which causes Swarm to undo the update if too many tasks fail during rollout.

Best Practices

Run an Odd Number of Managers

Swarm managers use the Raft consensus algorithm, which requires a majority to make decisions. Use three or five managers for high availability, and always an odd number to avoid split-brain scenarios. Do not scale managers beyond seven, as consensus overhead grows with each additional manager.

Separate Managers and Workers

Keep manager nodes dedicated to cluster management and scheduling. Run workloads on worker nodes using placement constraints. This prevents noisy applications from interfering with cluster coordination:

deploy:
  placement:
    constraints:
      - node.role == worker

Pin Stateful Services to Specific Nodes

For services that rely on local volumes, such as databases, use placement constraints to keep them on a designated node. Combine this with labeled nodes for clarity:

docker node update --label-add db=true worker1
deploy:
  placement:
    constraints:
      - node.labels.db == true

Use Healthchecks

Define healthchecks in your images or Compose files so Swarm can detect and restart unhealthy containers automatically:

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 5s
  retries: 3
  start_period: 10s

Set Resource Limits

Always define CPU and memory limits in your deploy configuration to prevent a single service from starving the rest of the cluster:

deploy:
  resources:
    limits:
      cpus: "1.0"
      memory: 1G
    reservations:
      cpus: "0.25"
      memory: 256M

Use a Private Registry

For production, store images in a private registry and authenticate Swarm to it. Create a registry secret and reference it in your service:

docker secret create registry_auth ~/.docker/config.json

Monitor and Log Centrally

Swarm does not include built-in monitoring or log aggregation. Pair it with tools like Prometheus, Grafana, and the ELK or Loki stack. Use a logging driver to ship logs to a central location:

docker service create \
  --name api \
  --log-driver gelf \
  --log-opt gelf-address=udp://logstash:12201 \
  myregistry/api:1.0.0

Back Up Manager State

Regularly back up the Swarm manager data directory, typically located at /var/lib/docker/swarm, on each manager node. This allows you to recover the cluster in the event of catastrophic failure.

Conclusion

Docker Swarm is not a competitor trying to out-feature Kubernetes; it is a focused, pragmatic tool that excels when simplicity, speed, and a small operational footprint matter most. For small teams, internal tools, edge deployments, and workloads that do not require the full machinery of Kubernetes, Swarm delivers reliable orchestration with a learning curve measured in hours rather than weeks. By understanding its strengths and limitations, applying the best practices outlined in this tutorial, and leveraging its tight integration with Docker Compose, you can build and operate production-grade clusters that are easy to understand, quick to deploy, and inexpensive to maintain. Choose Swarm when its simplicity aligns with your needs, and reach for Kubernetes only when the complexity of your platform truly demands it.

— Ad —

Google AdSense will appear here after approval

← Back to all articles