docker stack deploy: Basics for Swarm Stacks in Practice
AI generated
FROM
RUN
Docker · Swarm · Deployment · DevOps
docker stack deploy
Basics for Swarm stacks in practice

docker stack deploy turns a familiar compose file into a complete, highly available Swarm stack, including networks, volumes, secrets and configs in a single rollout. Knowing the differences between local compose and stack deployment helps you avoid the most common pitfalls when moving from development to production.

17 min read docker stack deploy · Compose · Secrets · Configs Docker 25+ · Compose Spec v3

1. What docker stack deploy actually does

The command docker stack deploy converts a declarative compose definition into a complete Swarm stack, consisting of multiple services managed together as a logical unit. Unlike docker compose up, which is primarily meant for local development, docker stack deploy talks directly to the Swarm API and creates services instead of individual containers. Each service can run in multiple replicas, gets distributed across available nodes by the Swarm scheduler, and is automatically restarted on failure.

The central advantage of docker stack deploy is one step provisioning. A single compose file describes services, networks, volumes, secrets and configs together, and a single call brings all components into the desired state. This considerably reduces the error potential of manually creating individual resources, because Docker itself calculates the difference between the actual state and the compose definition and only applies the necessary changes.

2. Adapting a compose file for Swarm

Not every local compose file works unchanged with docker stack deploy. The command ignores certain fields that only make sense for local development, above all build. A stack deployment expects finished images from a registry, not local building from a Dockerfile. Anyone working locally with build must build an image, tag it, and push it to a registry reachable by every node before the stack deployment.

Instead, docker stack deploy uses the deploy key of the compose specification, which is completely ignored locally. It defines replica count, resource limits, update strategies and placement constraints. This split between development relevant and production relevant fields lets you maintain the same base file for both environments, as long as you understand which fields get evaluated in which context.


# docker-compose.prod.yml — production stack for docker stack deploy
version: "3.9"

services:
  api:
    image: registry.example.com/shop-api:1.4.0   # pre-built image, no "build" key
    ports:
      - "8080:8080"
    networks:
      - backend
    deploy:
      replicas: 4
      resources:
        limits:
          cpus: "0.50"
          memory: 512M
        reservations:
          memory: 256M
      restart_policy:
        condition: on-failure
        max_attempts: 3
      placement:
        constraints:
          - node.role == worker

  db:
    image: mysql:8.4
    volumes:
      - db-data:/var/lib/mysql
    networks:
      - backend
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.labels.storage == fast-disk

networks:
  backend:
    driver: overlay

volumes:
  db-data:

3. The first stack rollout step by step

A stack rollout with docker stack deploy always starts with an initialized Swarm cluster. Without active Swarm mode, Docker rejects the command with a clear error message. Once the cluster is ready, docker stack deploy -c docker-compose.prod.yml shop is enough to roll out the entire stack under the name shop. Docker automatically creates all networks and volumes defined in the compose file, provided they do not already exist, and then starts the services at the specified replica count.

After the first rollout, an immediate check with docker stack services shop is recommended, to see whether all services reached the desired replica count. The state 4/4 in the REPLICAS column shows that all four instances started successfully. If the number deviates, for example 2/4, it is worth looking at the task history to understand why individual replicas failed to start.


# Verify Swarm mode is active before deploying
docker info --format '{{.Swarm.LocalNodeState}}'

# Deploy the full stack from a compose file
docker stack deploy -c docker-compose.prod.yml shop

# Check rollout status: replica counts per service
docker stack services shop

# Watch tasks for a specific service in real time
watch -n 2 'docker service ps shop_api --no-trunc'

4. Networks and volumes in the stack context

Networks within a docker stack deploy rollout are overlay networks by default, which enable container communication across multiple nodes. Unlike the default bridge network of docker compose up, an overlay network works cluster wide, so a service on node A can reach a service on node B through its name, without needing to manage IP addresses manually. Every stack also automatically gets its own default network prefixed with the stack name, unless an explicit network was defined.

Volumes behave differently in a Swarm stack than many expect. A named volume gets created locally on the node where the respective container task runs, it is not automatically replicated cluster wide. For a database service with only one replica and a fixed node placement rule, this is uncritical, but for multiple replicas spread across different nodes, an external storage solution such as NFS, GlusterFS, or a cloud storage driver is needed instead, so that all instances access the same data.

5. Secrets and configs instead of environment variables

docker stack deploy supports native secrets and configs, which are considerably safer than environment variables in the compose file. A secret gets stored encrypted in the Swarm managers Raft log and only gets mounted at runtime as a temporary file under /run/secrets/ inside the container, never as an environment variable that could show up in logs or process lists. Configs work similarly, but are meant for non sensitive configuration files like Nginx templates or application configurations.

The workflow starts by creating the secret through the Docker CLI before the stack references it. If a secret value changes, a new secret with a new name has to be created and referenced in the compose file, an existing secret cannot be changed afterward for security reasons. This behavior forces clean versioning of sensitive values, but also prevents a single wrong value from unnoticeably affecting all running containers.


# Create a secret from a file (never commit the source file to git)
docker secret create db_password ./secrets/db_password.txt

# Create a config from a template file
docker config create nginx_conf ./config/nginx.conf

# Reference both in the compose file under the "secrets" and "configs" keys,
# then deploy — Docker mounts them at runtime automatically
docker stack deploy -c docker-compose.prod.yml shop

# List currently registered secrets and configs
docker secret ls
docker config ls

6. Stack updates and re-deployment

A key advantage of docker stack deploy is the idempotence of the command. Calling it again with the same compose file but a changed image tag only updates the affected services and leaves unchanged services untouched. Docker compares the new definition with the current state and applies only the difference, instead of recreating the entire stack. This makes repeated deployments safe and predictable, even if only a single value changed between two rollouts.

For rolling updates of individual services, the update_config section in the deploy block controls parallelism and delay between batches. Running docker stack deploy again with an updated image tag automatically triggers a rolling update, where old containers get replaced step by step by new ones, without the service going completely offline. This property makes the command the central tool for continuous deployments in CI pipelines.

7. Diagnostics: inspecting stack, services and tasks

When a rollout does not go as expected, the Docker CLI provides several layers of diagnostics. docker stack ps shop shows all tasks of the entire stack with their current status, including failed attempts and their error messages. This overview is the first place to look when replicas fail to reach the desired count, because it immediately shows whether a task keeps restarting or is stuck permanently in the Rejected state.

For deeper diagnostics of individual services, docker service logs shop_api provides the aggregated logs from all replicas of a service, which is especially helpful when an error only occurs on certain nodes. docker service inspect shop_api --pretty shows the full configuration, including applied resource limits and placement rules, which often reveals that a constraint accidentally finds no matching node in the cluster.


# Show all tasks in the stack, including failed attempts
docker stack ps shop --no-trunc

# Aggregate logs from all replicas of a single service
docker service logs -f shop_api

# Full configuration dump for troubleshooting placement issues
docker service inspect shop_api --pretty

# Force a full re-evaluation of a stuck service
docker service update --force shop_api

8. Common pitfalls with docker stack deploy

The most common mistake with a first use of docker stack deploy is using a build key, which gets silently ignored. The result is an error message that an image cannot be found, even though it exists locally, because Swarm does not access the local image cache of the development machine. Every node in the cluster must either have built the referenced image itself or be able to pull it from a registry reachable by every node.

A second common mistake involves placement rules that find no matching node. A constraint like node.labels.storage == fast-disk causes a service to remain permanently in the Pending state if no node carries this label. In this case, the task status usually shows an inconspicuous message like no suitable node, which is easy to overlook if you only check the replica count in the overview instead of looking at the task details.

9. docker stack deploy compared to docker compose up

Both commands use the same base syntax but differ considerably in their target behavior. The following table compares the most important differences that become relevant when moving from local development to production.

Aspect docker compose up docker stack deploy
Target Local containers, a single host Swarm services, multiple nodes
build key Evaluated, builds locally Ignored, image must already exist
Scaling --scale flag on invocation deploy.replicas in compose
Secrets Mounted as files, local Encrypted in Raft log, cluster wide
Rolling updates Not built in Native via update_config

In practice, many teams maintain two compose files: a base file with shared settings and an overlay file specifically for docker stack deploy, merged via docker compose -f base.yml -f prod.yml config and then passed to the stack command. This split keeps development and production fields cleanly separated without maintaining two completely independent files.

Mironsoft

Docker Swarm deployments and infrastructure automation

Stable Swarm stacks instead of fragile ad hoc deployments?

We build production ready docker stack deploy workflows for your shop or API, including secrets management, rolling updates and CI integration.

Stack design

Structuring compose files for Swarm and making them production ready

Secrets & configs

Secure management of sensitive values without plaintext in repositories

CI integration

Automated stack rollouts directly from the pipeline

10. Summary

docker stack deploy is the central command for productive Swarm deployments and replaces manually creating individual services with a declarative, repeatable definition. The compose file needs to be deliberately adapted for production: no build key, instead the deploy block with replica count, resource limits and update strategy. Native secrets and configs replace insecure environment variables and are managed encrypted inside the cluster.

The diagnostic tools docker stack ps, docker service logs and docker service inspect cover the most common problems, from missing images to unfulfillable placement rules. Once you understand these basics, docker stack deploy can be reliably integrated into CI pipelines, giving you a reproducible, versioned deployment process without manual intervention on the server.

docker stack deploy: the essentials at a glance

Compose adaptation

No build key, finished images from a registry, use the deploy block for replicas and limits.

Rollout

A single command brings services, networks, volumes, secrets and configs into the target state.

Secrets

Encrypted in the Raft log, never as an environment variable, new values require new secret names.

Diagnostics

docker stack ps, docker service logs and docker service inspect cover most problems.

11. FAQ: docker stack deploy

1Can it build an image directly?
No, build is ignored. Build, tag and push the image to a reachable registry beforehand.
2What happens on repeated deploy of the same name?
Idempotent, only changed services get updated, unchanged ones remain untouched.
3How to change an existing secret?
Not changeable directly, create a new secret with a new name and reference it, remove the old one after.
4Why does a service stay Pending?
Usually a missing placement constraint match. docker service ps --no-trunc shows the exact cause.
5Does every node need registry access?
Yes, every node must have the image locally or be able to pull it from the registry.
6How to remove the whole stack?
docker stack rm shop removes services, networks and configs, volumes are kept.
7Combine multiple compose files?
Yes, with multiple -c flags, later files override values from earlier ones.
8Is depends_on supported?
No, ignored. Use wait for patterns or health checks in the application itself.
9How to see rolling update progress?
docker service ps shows new and old tasks, complete once all active tasks are Running.
10Suitable for Magento deployments?
Yes, with external storage for static content and media files across multiple nodes.