Skip to content
Codeloom
DevOps

Container Orchestration: Docker Swarm vs Kubernetes

Compare Docker Swarm and Kubernetes for container orchestration. Learn the architecture, setup, scaling, and networking of both platforms with practical examples.

·9 min read · By Codeloom
Intermediate 16 min read

What you'll learn

  • What container orchestration solves and why you need it
  • Docker Swarm architecture, setup, and service management
  • Kubernetes architecture, core concepts, and deployment patterns
  • When to choose Swarm vs Kubernetes for your workloads

Prerequisites

  • Comfortable building and running Docker containers
  • Basic understanding of networking concepts
  • Command-line experience on Linux or macOS

Why Container Orchestration?

Running a single container on a single machine is simple. Running dozens of containers across multiple machines is not. Container orchestration solves the problems that appear at scale:

  • Scheduling: Which machine should each container run on, based on available resources?
  • Scaling: How do you add or remove container instances based on demand?
  • Networking: How do containers find and communicate with each other across machines?
  • Health management: What happens when a container crashes or a machine goes down?
  • Rolling updates: How do you deploy new versions without downtime?
  • Service discovery: How does one service locate another without hardcoded addresses?

Docker Swarm and Kubernetes are the two most prominent solutions. They approach these problems differently, with different trade-offs in complexity, capability, and operational overhead.

Docker Swarm

Docker Swarm is Docker’s native orchestration solution. It is built into the Docker Engine, which means you do not need to install anything extra if you already have Docker. Its design philosophy prioritizes simplicity.

Architecture

Swarm uses a manager-worker architecture:

  • Manager nodes maintain the cluster state, schedule services, and serve the Swarm API. You should run an odd number (3 or 5) for high availability via Raft consensus.
  • Worker nodes run the containers. They receive tasks from managers and report their status back.

Setting Up a Swarm Cluster

Initialize the Swarm on the first manager:

# On the manager node
docker swarm init --advertise-addr 192.168.1.10

This outputs a join token. Use it on worker nodes:

# On each worker node
docker swarm join --token SWMTKN-1-abc123... 192.168.1.10:2377

Add additional managers for high availability:

# Get the manager join token
docker swarm join-token manager

# On additional manager nodes
docker swarm join --token SWMTKN-1-xyz789... 192.168.1.10:2377

Verify the cluster:

docker node ls
# ID          HOSTNAME    STATUS    AVAILABILITY    MANAGER STATUS
# abc123 *   manager-1   Ready     Active          Leader
# def456     manager-2   Ready     Active          Reachable
# ghi789     worker-1    Ready     Active
# jkl012     worker-2    Ready     Active

Deploying Services

Create a service in Swarm:

docker service create \
  --name web \
  --replicas 3 \
  --publish 80:8080 \
  --update-delay 10s \
  --update-parallelism 1 \
  --restart-condition on-failure \
  myregistry/web-app:v1.0

Or use a Docker Compose file with docker stack deploy:

# docker-compose.yml
version: "3.8"

services:
  web:
    image: myregistry/web-app:v1.0
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
      rollback_config:
        parallelism: 1
        delay: 5s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 256M
        reservations:
          cpus: "0.1"
          memory: 128M
    ports:
      - "80:8080"
    networks:
      - app-network
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3

  redis:
    image: redis:7-alpine
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager
    volumes:
      - redis_data:/data
    networks:
      - app-network

networks:
  app-network:
    driver: overlay

volumes:
  redis_data:

Deploy the stack:

docker stack deploy -c docker-compose.yml myapp

# Check services
docker stack services myapp

# Check tasks (individual containers)
docker service ps myapp_web

# Scale a service
docker service scale myapp_web=5

# Update the image
docker service update --image myregistry/web-app:v1.1 myapp_web

# Roll back if something goes wrong
docker service rollback myapp_web

Swarm Networking

Swarm creates an overlay network that spans all nodes. Services on the same overlay network can reach each other by service name:

# From inside a container on the app-network
curl http://redis:6379  # Service discovery by name

Swarm also includes a built-in load balancer called the routing mesh. Any node in the swarm can accept traffic for a published port, even if that node is not running a task for the service. The mesh routes the request to a node that is.

Swarm Secrets

Store sensitive data securely:

# Create a secret
echo "my-db-password" | docker secret create db_password -

# Use it in a service
docker service create \
  --name api \
  --secret db_password \
  myregistry/api:v1.0

Inside the container, the secret is available at /run/secrets/db_password.

Kubernetes

Kubernetes (K8s) is the industry standard for container orchestration. It is more complex than Swarm but offers significantly more features, extensibility, and ecosystem support.

Architecture

Kubernetes has a control plane and worker nodes:

Control plane components:

  • API Server: The front door for all operations, accepts REST requests.
  • etcd: Distributed key-value store holding all cluster state.
  • Scheduler: Assigns pods to nodes based on resource requirements and constraints.
  • Controller Manager: Runs control loops that maintain desired state (e.g., ensuring the right number of replicas exist).

Worker node components:

  • kubelet: Agent that runs on each node, manages pods.
  • kube-proxy: Handles networking rules for service communication.
  • Container runtime: Runs containers (containerd, CRI-O).

Setting Up a Local Cluster

For development, use kind (Kubernetes in Docker):

# Install kind
brew install kind  # macOS
# or
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64 && chmod +x ./kind && sudo mv ./kind /usr/local/bin/

# Create a multi-node cluster
cat <<EOF | kind create cluster --config=-
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
  - role: worker
EOF

# Verify
kubectl get nodes

Core Concepts

Pod: The smallest deployable unit. Usually contains one container but can hold multiple tightly coupled containers.

Deployment: Manages a set of identical pods with declarative updates.

Service: Provides a stable network endpoint for a set of pods.

Namespace: Logical isolation boundary within a cluster.

ConfigMap / Secret: Externalized configuration and sensitive data.

Deploying Applications

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: myregistry/web-app:v1.0
          ports:
            - containerPort: 8080
          env:
            - name: DATABASE_URL
              valueFrom:
                secretKeyRef:
                  name: app-secrets
                  key: database-url
          readinessProbe:
            httpGet:
              path: /ready
              port: 8080
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 15
            periodSeconds: 20
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: production
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 8080
  type: ClusterIP
# Apply the manifests
kubectl apply -f deployment.yaml

# Watch the rollout
kubectl rollout status deployment/web -n production

# Scale
kubectl scale deployment/web --replicas=5 -n production

# Update the image
kubectl set image deployment/web web=myregistry/web-app:v1.1 -n production

# Roll back
kubectl rollout undo deployment/web -n production

Horizontal Pod Autoscaling

Kubernetes can automatically scale based on CPU, memory, or custom metrics:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web
  namespace: production
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80

Swarm has no built-in autoscaling; you need external tools or scripts.

Kubernetes Networking with Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web
  namespace: production
  annotations:
    nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
  ingressClassName: nginx
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: web
                port:
                  number: 80
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls

Head-to-Head Comparison

FeatureDocker SwarmKubernetes
Setup complexityMinutesHours (or use managed service)
Learning curveLowSteep
ScalingManual or scriptedBuilt-in HPA, VPA, cluster autoscaler
NetworkingOverlay with routing meshCNI plugins, Ingress controllers
StorageVolume driversCSI, PV/PVC, StorageClasses
EcosystemLimitedMassive (Helm, operators, service mesh)
ConfigurationDocker Compose filesYAML manifests, Helm charts, Kustomize
RBACBasicFine-grained
Self-healingRestarts failed containersRestarts, reschedules, replaces
CommunitySmall, decliningEnormous, growing
Managed offeringsNoneEKS, GKE, AKS, and many more

When to Choose What

Choose Docker Swarm when:

  • Your team is small and already comfortable with Docker Compose.
  • You have a handful of services (under 20) running on a few nodes.
  • You need to get something running quickly without a steep learning investment.
  • You do not need advanced features like custom autoscaling, service mesh, or complex RBAC.

Choose Kubernetes when:

  • You are running many services at scale across dozens or hundreds of nodes.
  • You need autoscaling, advanced networking, or fine-grained access control.
  • You want access to the vast Kubernetes ecosystem (Helm charts, operators, service mesh).
  • You can use a managed Kubernetes service (EKS, GKE, AKS) to reduce operational burden.
  • Your organization is investing in platform engineering.

For most teams starting today, managed Kubernetes is the practical choice. Services like GKE Autopilot or EKS with Fargate eliminate much of the operational complexity while giving you access to the full Kubernetes ecosystem. Swarm remains a valid choice for simple workloads where operational simplicity is the top priority.

Wrapping Up

Container orchestration is essential once you move beyond a single machine. Docker Swarm offers the shortest path from Docker Compose to a multi-node cluster, with familiar tooling and minimal configuration. Kubernetes provides a more powerful and extensible platform at the cost of increased complexity. The right choice depends on your team size, workload complexity, and how much of the Kubernetes ecosystem you need. Start with whichever gets you to production fastest, and migrate to Kubernetes when your needs outgrow Swarm’s capabilities.