Deploy Docker Swarm Stacks
Deploy Docker stacks with Swarm mode. This lesson teaches how to use Docker Swarm to deploy multi-service applications as stacks, including practical exercises and next-step guidance.
Focus: deploy docker stacks with swarm mode
So you've mastered Docker Compose for local development, but when you try to run those same services in production, things fall apart — scaling bottlenecks, single-node failures, and no built-in rolling updates. Simply running docker-compose up on a server leaves you with a fragile, manually-managed setup. You need a way to declaratively define your entire multi-service application and deploy it onto a resilient cluster that handles failures and scaling automatically. This is exactly what Docker Swarm stacks provide: a production-grade, native orchestration layer that treats your Compose file as a deployment blueprint.
The problem this lesson solves
Running containers on a single Docker host is fine for prototyping, but it creates a single point of failure. If that machine goes down, your application goes with it. Even if you cluster multiple hosts manually, you're left orchestrating network overlay, load balancing, and service discovery by hand — a fragile, error-prone nightmare. Docker Swarm mode solves this by turning a pool of Docker hosts into a single, logical cluster with built-in high availability, load balancing, and declarative scaling. The "stack" concept takes your existing docker-compose.yml (with minor adjustments) and deploys it across the entire Swarm, managing the full lifecycle of your multi-service application.
Core concept / mental model
Think of a Docker Swarm stack as the production version of a Compose project. You write your application definition in a Compose file (YAML), then submit it to the Swarm manager. The manager interprets that file as a stack — it creates and manages all necessary services, networks, and volumes across the cluster.
- Service: A declarative definition of a container's image, replicas, ports, environment variables, and update strategy. The Swarm scheduler ensures the desired number of replicas are running on healthy nodes.
- Stack: A collection of related services that form a complete application. It groups them under one logical name and manages them as a unit.
- Swarm: The underlying cluster of Docker hosts (manager + worker nodes) that provides the orchestration engine.
Pro tip: If you understand
docker-compose.yml, you're 90% of the way to understanding a Swarm stack. The key differences are: you removeversion(Swarm uses the Compose v3 schema), adddeploy:keys for scaling and update config, and you usedocker stack deployinstead ofdocker compose up.
How it works step by step
- Initialize the Swarm — On the manager node, run
docker swarm init. This creates the control plane and generates a manager token. - Join worker nodes — On each worker node, run
docker swarm join --token <token> <manager-ip>:2377. This registers the worker in the cluster. - Write your stack file — Create a Compose file (e.g.,
stack.yml) that defines your services, networks, and volumes. Adddeploy:sections to control scaling, restart policy, and update behavior. - Deploy the stack — From the manager node, execute
docker stack deploy -c stack.yml <stack_name>. The manager analyzes the file and creates all resources. - Verify and manage — Use
docker stack services <stack_name>to list running services,docker stack ps <stack_name>to see individual tasks (replicas), anddocker service scale <service_name>=<count>to adjust replicas. - Update the stack — Modify your stack file, then run
docker stack deploy -c stack.yml <stack_name>again. Swarm performs a rolling update based on theupdate_configin your deploy block.
The cause-and-effect chain is: your static YAML file → Swarm manager interprets it → creates/updates services → scheduler places tasks (containers) on available nodes → built-in load balancer (routing mesh) distributes traffic to healthy replicas.
Hands-on walkthrough
Let's build a real stack. You'll create a simple web app with a Python web server and a Redis cache, deployed across your local Swarm (simulating a cluster with multiple nodes locally).
Step 1: Initialize a single-node Swarm (for testing)
docker swarm init
Expected output:
Swarm initialized: current node (xxxx) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-... <IP>:2377
Step 2: Create stack.yml
Save this as stack.yml:
services:
web:
image: python:3.11-slim
command: python -m http.server 80
ports:
- target: 80
published: 8080
protocol: tcp
mode: ingress
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
restart_policy:
condition: on-failure
networks:
- frontend
cache:
image: redis:7-alpine
deploy:
replicas: 1
placement:
constraints:
- node.role == manager
networks:
- backend
networks:
frontend:
driver: overlay
backend:
driver: overlay
Step 3: Deploy the stack
docker stack deploy -c stack.yml myapp
Expected output:
Creating network myapp_frontend
Creating network myapp_backend
Creating service myapp_web
Creating service myapp_cache
Step 4: Verify the deployment
docker stack services myapp
docker stack ps myapp
The first command shows each service with its replicas. The second shows the individual container tasks and which node they're running on.
Step 5: Test scaling and updates
Scaling the web service on the fly (without modifying the file):
docker service scale myapp_web=5
Then update the image (simulate a new version):
# Modify stack.yml to use 'python:3.12-slim', then redeploy
docker stack deploy -c stack.yml myapp
Watch the rolling update:
docker service ps myapp_web
You'll see tasks gradually replaced, respecting the parallelism and delay you defined in update_config.
Compare options / when to choose what
| Feature | Docker Swarm Stacks | Kubernetes (K8s) | Plain Docker Compose |
|---|---|---|---|
| Setup complexity | Simple (built into Docker Engine) | Complex (needs control plane setup) | Trivial (local) |
| Built-in load balancing | Routing mesh (ingress) | Services + Ingress controllers | Port mapping only |
| Scaling | docker service scale |
kubectl scale |
Manual (not designed for multi-node) |
| Rolling updates | Supported via update_config |
Supported via Deployment strategy |
Not natively supported |
| Secret management | Docker secrets (v1) | Kubernetes secrets | Not built-in |
| Best for | Small to medium deployments, teams already using Docker | Large-scale, complex orchestration needs | Local dev & single-node testing |
When to choose Swarm stacks: You want native Docker integration, minimal operational overhead, and a familiar Compose-like syntax for production. It's ideal for teams that don't need K8s' complexity but still need multi-node resilience.
When to choose something else: If you need advanced auto-scaling, service mesh, or heterogeneous container orchestration (e.g., mixed Linux/Windows, complex ingress), Kubernetes is more capable. If you're on a single node, plain Compose is simpler.
Troubleshooting & edge cases
- "This node is not a swarm manager" — Run
docker swarm initfirst. Workers cannot deploy stacks. - "could not find an available, non-overlapping IPv4 address pool" — Docker's overlay network address pool is exhausted. Reset with
docker swarm leave --force, thendocker swarm init --default-addr-pool 10.10.0.0/16. - "No such image" on worker nodes — The image must exist on every node (or be pullable from a registry). For private images, use
docker loginon each node or create a Docker registry service as part of your stack. - Port conflicts — The
mode: ingressuses the published port on every node. If a service uses the same published port as an existing service, the stack deploy will fail. Use different ports ormode: host. - Network not created — If you manually remove a stack network, subsequent deploy fails silently. Leave the stack first with
docker stack rm <stack_name>.
Pro tip: Use
docker stack deploy --prune -c stack.yml myappto automatically remove services or networks that are no longer in your compose file. This prevents orphaned resources.
What you learned & what's next
You now understand how to deploy Docker stacks with Swarm mode — from initializing a cluster, writing a stack file, deploying it, scaling services, and performing rolling updates. You've seen how stacks solve the production readiness gap by adding built-in high availability, load balancing, and declarative management on top of your familiar Compose workflow.
In the next lesson, you'll learn Docker Stack Configuration Management — how to use Docker configs and secrets to manage environment-specific configuration and sensitive data across your Swarm stacks, keeping your application secure and portable across environments.
Practice recap
Create a stack file with two services: a Python Flask app (3 replicas) and a PostgreSQL database (1 replica, with a placement constraint to run only on the manager node). Deploy it to a single-node Swarm, then simulate a failure by stopping one of the Flask containers — observe how the Swarm recreates it automatically. Finally, perform a rolling update by changing the Flask image tag and redeploying the stack.
Common mistakes
- Forgetting to initialize the Swarm before deploying a stack — you'll get 'this node is not a swarm manager'.
- Using
docker-compose upinside a Swarm cluster instead ofdocker stack deploy— stack features like scaling and rolling updates won't work. - Not adding
deploy:sections to your Compose file, then wondering why scaling viadocker service scalehas no effect on the original compose setup. - Assuming all images are available on every node — worker nodes fail if they can't pull the image (especially private images).
Variations
- Use
docker stack deploywith YAML files that include Compose spec v3.8 (or later) for advanced features like secrets and configs. - For production, combine your stack with Docker secrets (
secrets:in YAML) to manage API keys and passwords securely. - If you need hybrid workloads (Linux + Windows containers), Swarm supports mixed clusters, but each service must target its appropriate OS via
placement:constraints.
Real-world use cases
- Deploy a microservices e-commerce backend (cart, payment, inventory) into a production cluster with 3 replicas per service for high availability.
- Run a CI/CD pipeline worker pool where each worker is a service that scales automatically based on queue depth (e.g., Jenkins agents on Swarm).
- Host a WordPress site with separate services for web, database, and caching, all updated via rolling updates with zero downtime.
Key takeaways
- A Swarm stack is the production equivalent of a Compose project — it deploys multi-service applications across a cluster.
- You initialize the Swarm with
docker swarm init, then deploy stacks withdocker stack deploy -c stack.yml <name>. - Stacks support built-in rolling updates via
update_configin your deploy block, enabling zero-downtime deployments. - The routing mesh (ingress mode) automatically load balances traffic across all healthy replicas of a service.
- Stacks are managed using
docker stack,docker service, anddocker nodecommands — notdocker-compose. - For edge cases like exhausted IP pools or port conflicts, resetting the swarm or using host mode ports can help.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.