Skip to content

How to Update Odoo in Docker Without Downtime

DeployMonkey Team · March 11, 2026 7 min read

Updating Odoo in Docker is safer than a native install — you can roll back in minutes if something goes wrong. But "safer" does not mean "automatic." Done carelessly, an upgrade can corrupt your database or leave your instance broken. This guide gives you the exact sequence to update Odoo in Docker with the shortest possible downtime.

Before You Touch Anything: Understand the Risk

Odoo upgrades fall into two categories:

  • Minor updates (e.g., 17.0.1 → 17.0.2): Usually safe. Mostly bug fixes and security patches. Module schema rarely changes.
  • Major version upgrades (e.g., 16 → 17): Require running the official Odoo migration scripts. Never do this by just swapping Docker image tags.

This guide covers minor updates within the same major version. Major version upgrades deserve their own process and should always be done on a staging environment first.

Step 1: Check the Current Version

# Find your running container name
docker compose ps

# Check current Odoo version
docker compose exec odoo odoo --version

Also check the Odoo release notes or Docker Hub for what changed in the new image before updating.

Step 2: Pull the New Image

# Pull without stopping anything — this runs in the background
docker compose pull odoo

Docker will download the new image layers while your current container keeps running. Users stay online during this step.

Step 3: Back Up the Database

Never skip this. Even for patch-level updates:

# Create a timestamped backup
BACKUP_DATE=$(date +%Y%m%d_%H%M%S)

# Dump the database from inside the running db container
docker compose exec db pg_dump -U odoo odoo \
  | gzip > /opt/backups/odoo_pre_update_${BACKUP_DATE}.sql.gz

# Verify the backup is not empty
ls -lh /opt/backups/odoo_pre_update_${BACKUP_DATE}.sql.gz

Also back up the filestore (attachments):

tar -czf /opt/backups/filestore_${BACKUP_DATE}.tar.gz \
  $(docker volume inspect odoo_odoo_data --format '{{.Mountpoint}}')

Step 4: Stop the Odoo Container (Not the Database)

# Stop only Odoo, keep the database running
docker compose stop odoo

# Confirm it stopped
docker compose ps

Keeping PostgreSQL running avoids the cold-start delay when you bring it back up. Total downtime starts here.

Step 5: Start Odoo with the New Image and Run Updates

# Start Odoo with -u base to apply schema updates
docker compose run --rm odoo odoo \
  -d odoo \
  -u base \
  --stop-after-init \
  --no-http

# If you have custom modules, update them too
docker compose run --rm odoo odoo \
  -d odoo \
  -u your_custom_module \
  --stop-after-init \
  --no-http

The --stop-after-init flag runs migrations and exits cleanly. The --no-http flag prevents it from trying to serve web traffic during the update run.

Step 6: Start the Updated Container

docker compose up -d odoo

# Watch the startup logs
docker compose logs -f odoo

Watch for errors about failed migrations, missing columns, or import errors. A clean startup looks like:

odoo  | 2026-03-11 10:00:00,000 1 INFO odoo odoo.service.server: HTTP service (werkzeug) running on 0.0.0.0:8069

Step 7: Verify the Update

# Check the new version
docker compose exec odoo odoo --version

# Hit the health endpoint
curl -s http://localhost:8069/web/health

# Check for errors in recent logs
docker compose logs odoo --since 10m | grep -i error

Log in to the Odoo UI and check Settings → Technical → Database Structure → Installed Modules. Confirm your key modules show the expected version numbers.

Step 8: Roll Back If Needed

If something is broken, rolling back is straightforward:

# Stop the new container
docker compose stop odoo

# Edit docker-compose.yml to pin the previous image tag
# Then restore the database
gunzip -c /opt/backups/odoo_pre_update_TIMESTAMP.sql.gz \
  | docker compose exec -T db psql -U odoo odoo

# Bring up the old version
docker compose up -d odoo

Automating Minor Updates Safely

For teams that want automated updates, use a staging environment pattern:

#!/bin/bash
# update-odoo.sh — run on staging first, promote after validation

set -euo pipefail

COMPOSE_FILE="/opt/odoo/docker-compose.yml"
BACKUP_DIR="/opt/backups"
DATE=$(date +%Y%m%d_%H%M%S)

echo "Backing up database..."
docker compose -f "$COMPOSE_FILE" exec db \
  pg_dump -U odoo odoo | gzip > "$BACKUP_DIR/pre_update_$DATE.sql.gz"

echo "Pulling new image..."
docker compose -f "$COMPOSE_FILE" pull odoo

echo "Stopping Odoo..."
docker compose -f "$COMPOSE_FILE" stop odoo

echo "Running migrations..."
docker compose -f "$COMPOSE_FILE" run --rm odoo odoo \
  -d odoo -u base --stop-after-init --no-http

echo "Starting updated Odoo..."
docker compose -f "$COMPOSE_FILE" up -d odoo

echo "Done. Check logs: docker compose logs -f odoo"

How DeployMonkey Handles Odoo Updates

On DeployMonkey, minor Odoo updates are applied automatically with zero manual steps. We pull the new image, run a pre-update snapshot (stored in S3), apply migrations, verify the healthcheck passes, and only then route traffic to the updated container. If the healthcheck fails within 60 seconds, we automatically roll back to the previous image and restore the snapshot.

You get a notification either way — update succeeded or rolled back — without doing anything yourself. This is the kind of operational reliability that takes months to build on a self-managed server. It comes standard on every DeployMonkey plan.

Try DeployMonkey free — no credit card required.

Frequently Asked Questions

Can I update Odoo without any downtime at all?

True zero-downtime Odoo upgrades require running two Odoo instances simultaneously (blue-green deployment) with a load balancer switching traffic after the new version passes health checks. This is complex to set up and only worthwhile for large deployments. For most businesses, a 2–5 minute maintenance window during a low-traffic period is the practical answer.

Do I need to run -u base or -u all?

Use -u base for most patch updates — it updates the base module and triggers dependent module updates. Use -u all only if you have many third-party modules and want to ensure all are updated. -u all is slower and occasionally triggers spurious errors in poorly-maintained community modules.

What if the pg_dump command hangs?

A hanging pg_dump usually means there is a long-running transaction holding a lock. Stop the Odoo container first, then run pg_dump — with Odoo disconnected, no new transactions can start and existing ones will complete or be terminated.

How do I know which Odoo Docker image tag to use?

Use the major version tag (odoo:17) for automatic patch updates, or check Docker Hub for the latest specific tag. Avoid latest — it can jump major versions unexpectedly.