Odoo Docker Compose vs Swarm: Which One to Use

Odoo Docker Compose vs Swarm compared: hosts, filestore, secrets, updates and scaling, plus the exact changes to turn an Odoo compose file into a stack.

Updated . 4 min read

Odoo Docker Compose vs Swarm comes down to one question: will Odoo run on one server, or on several? Docker Compose runs an Odoo stack on a single host and suits development, testing and many small production setups. Docker Swarm runs the same kind of file across a cluster and adds rescheduling, rolling updates with rollback, encrypted secrets and multi-node placement. This guide compares the two for Odoo specifically and shows what changes when you move from one to the other.

Odoo on Compose vs Swarm, side by side

Docker ComposeDocker Swarm
HostsOneOne or many (managers + workers)
Commanddocker compose up -ddocker stack deploy -c file.yml name
File formatCompose specificationSame specification. Some keys are ignored, and deploy: matters more
Builds imagesYes (build:)No. Push images to a registry first
Odoo filestoreLocal named volumeLocal and pinned, or shared storage so tasks can move
Database passwordEnv var or file-based secret (a plain bind mount)Swarm secret, encrypted in the cluster store, mounted in memory
Restart on failurerestart: unless-stoppeddeploy.restart_policy, and tasks move to another node if their node dies
UpdatesRecreate the container (short downtime)Rolling update, health-checked, with automatic rollback
ScalingOdoo workers. --scale on one hostOdoo workers, plus replicas across nodes
RoutingPort mapping or a reverse proxy containerRouting mesh or a proxy such as Traefik reading service labels
Startup orderdepends_on with health conditionsIgnored. The app must wait or retry (the Odoo image already waits for PostgreSQL)

When Docker Compose is enough for Odoo

  • Development and testing, especially with build: for a custom Odoo image and bind-mounted addons.
  • One company on one server, where a few minutes of downtime during an upgrade is acceptable and the server is backed up.
  • CI pipelines that start Odoo and PostgreSQL, run tests and throw everything away.

Scaling on a single host happens through Odoo's workers setting, not through more containers. A full Compose setup is in Odoo Docker Compose.

When to move Odoo to Docker Swarm

  • You need Odoo to come back on its own when a server dies.
  • You want deploys without downtime: start the new container, check its health, then stop the old one.
  • You host several Odoo instances and want to spread them across servers with placement rules.
  • You want database and admin passwords kept as encrypted secrets rather than in env files.

Swarm is built into Docker Engine, so docker swarm init on a server you already have is enough to start. A one-node swarm still gives you rolling updates, secrets and stack files. This is the platform Easy Instance runs on: see how Easy Instance runs Odoo on Docker Swarm.

From an Odoo compose file to a stack file

A typical Compose file for Odoo 19 and PostgreSQL 16:

compose.yaml
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_USER: odoo
      POSTGRES_PASSWORD: change-me
      POSTGRES_DB: postgres
    volumes:
      - pg-data:/var/lib/postgresql/data
    restart: unless-stopped

  odoo:
    image: odoo:19.0
    depends_on:
      - db
    environment:
      HOST: db
      USER: odoo
      PASSWORD: change-me
    ports:
      - "8069:8069"
    volumes:
      - odoo-data:/var/lib/odoo
      - ./addons:/mnt/extra-addons
    restart: unless-stopped

volumes:
  pg-data:
  odoo-data:

To run it with docker stack deploy, change these things:

  1. Replace restart: with deploy.restart_policy. Swarm ignores restart.
  2. Drop depends_on. Swarm ignores it. The Odoo image's entrypoint waits for PostgreSQL, and Swarm restarts the task if it gives up.
  3. Move passwords into a secret. Run docker secret create odoo_db_password -, then use POSTGRES_PASSWORD_FILE for PostgreSQL and PASSWORD_FILE for Odoo. The official Odoo image reads it at startup.
  4. Bake addons into the image or put them on shared storage. A ./addons bind mount refers to a path on whichever node runs the task, and that path may not exist there.
  5. Decide where data lives. Either pin db and odoo to a labeled node, or put the Odoo filestore on shared storage (see Odoo filestore on NFS).
  6. Add deploy.update_config with order: start-first and failure_action: rollback, plus a health check, to get updates without downtime.
  7. Remove build: and container_name: if present. Swarm doesn't build images and names containers itself.

The finished stack file, with Traefik v3 and HTTPS, is in deploy an Odoo docker stack.

Can one file serve both?

Mostly. Docker Compose v2 reads deploy.resources and deploy.replicas, and Swarm ignores build and depends_on without failing. In practice teams keep a base file and add an override per environment. docker compose -f compose.yaml -f compose.dev.yaml up and docker stack deploy -c compose.yaml -c stack.prod.yaml odoo both merge files in order. Note that docker stack deploy takes ${VARIABLES} from your shell only. It doesn't read .env.

Or neither

If you'd rather not run either one, Easy Instance gives you managed Odoo with backups, staging and GitHub deploys. See how it compares to Odoo.sh or start a 10-day free trial, no credit card required.

Rather not run the server yourself?

Get managed Odoo hosting with backups, SSL, monitoring and updates handled for you. Free for 10 days.