✦ For everyone, free.

Practical knowledge for real and everyday life

Home

18.3.2.1 Compose Service Mapping

A focused guide to Compose Service Mapping, connecting core concepts with practical Docker and container operations.

Compose service mapping to Swarm clarifies exactly which fields within a Compose service definition are actually meaningful when deployed as a Swarm stack versus run as a plain, single-host Compose application, since the same Compose file format serves both purposes but several fields, particularly within the deploy section, are recognized only by one of the two deployment targets and silently ignored by the other.

Fields recognized only under Swarm

The entire deploy section, and everything nested within it, is specifically interpreted only when a Compose file is deployed as a Swarm stack through docker stack deploy; running the identical file through plain docker compose up ignores this section entirely:

services:
  api:
    deploy:
      replicas: 3
      resources:
        limits:
          memory: 512M
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.labels.zone == us-east
docker compose up -d
docker stack deploy -c docker-compose.yml my-stack

Running the first command against a file containing this deploy section produces a single container with none of these settings applied at all; only the second command, deploying as a genuine Swarm stack, actually respects replicas, resource limits, restart policy, and placement constraints as declared.

Fields recognized by both, with different effect

Several fields exist outside the Swarm-specific deploy section and apply to both deployment targets, but with meaningfully different underlying mechanisms even though the configuration syntax looks identical:

services:
  api:
    networks:
      - my-network

Under plain Compose, this attaches the container to a single-host bridge network; under a Swarm stack, the identical syntax attaches it to a cluster-spanning overlay network, the meaningfully different underlying mechanism covered in dedicated overlay networking content, even though the Compose file syntax expressing the intent is identical in both cases.

The restart field versus restart_policy

A point of frequent confusion is the top-level restart field versus the deploy.restart_policy field, which look similar but apply to entirely different deployment contexts:

services:
  api:
    restart: unless-stopped
services:
  api:
    deploy:
      restart_policy:
        condition: on-failure

The top-level restart field applies under plain Compose; the nested deploy.restart_policy applies under Swarm; including both is a reasonable way to express equivalent restart intent regardless of which deployment target a given file ends up being used with, though only one of the two actually takes effect for any given deployment method.

Build configuration is Swarm-incompatible

The build directive, used for building an image locally from a Dockerfile, has no meaning at all under Swarm, since stack deployment can only run already-built, pushed images that every node in the cluster can pull, rather than building from a local Dockerfile on whichever single host happens to run the docker stack deploy command:

services:
  api:
    build: .
ignoring deploy.build_args as it does not apply for stack deployment

A Compose file intended for genuine Swarm stack deployment should reference an already-built, pushed image directly rather than a build directive, since Swarm has no mechanism to build the image on every node that might need to run it.

Scale field versus deploy.replicas

An older, simpler way to set replica count, the top-level scale field, exists alongside the Swarm-specific deploy.replicas field, and understanding which one applies in which context avoids confusion when reviewing an older or mixed-convention Compose file:

services:
  api:
    scale: 3
services:
  api:
    deploy:
      replicas: 3

The scale field has historically applied under plain Compose specifically (where it sets how many container instances to run on the single host), while deploy.replicas is the Swarm-specific field for the same underlying concept; current Compose versions have evolved this distinction somewhat, making it worth verifying the exact current behavior against the specific Compose version in actual use rather than relying on older documentation alone.

A single file serving both purposes deliberately

Because plain Compose silently ignores the deploy section and Swarm relies on it specifically, a single, well-structured Compose file can genuinely serve both purposes, plain Compose for local development with the deploy section providing the additional configuration Swarm needs for production, without needing to maintain two structurally divergent files, provided the structure is understood and used deliberately rather than discovered accidentally through ignored fields.

services:
  api:
    build: .
    deploy:
      replicas: 3

This dual-purpose file would build locally for development through plain Compose while having no effect from the unused deploy section; deploying the same file to genuine Swarm would need the build directive replaced with an already-built image reference, since the two purposes diverge specifically at this one field.

Common mistakes

  • Assuming the deploy section's settings apply under plain Compose, when they are recognized and applied only when deployed as a genuine Swarm stack.
  • Confusing the top-level restart field with the nested deploy.restart_policy field, expecting one to apply in a context where only the other actually does.
  • Including a build directive in a Compose file intended for genuine Swarm stack deployment, not realizing Swarm cannot build images and requires an already-pushed reference instead.
  • Not verifying the actual current behavior of the scale field versus deploy.replicas against the specific Compose version in use, relying on potentially outdated documentation.
  • Assuming network configuration syntax identical between plain Compose and Swarm produces identical underlying networking behavior, rather than understanding the meaningfully different bridge-versus-overlay mechanism beneath the same syntax.

Compose service mapping between plain Compose and Swarm depends on understanding precisely which fields, particularly everything within deploy, are recognized only by one deployment target and silently ignored by the other, which is what allows, and also what complicates, using a single Compose file deliberately structured to serve both local development and genuine Swarm stack deployment.