Docker image
Odoo 18 in Docker. ERP and CRM, pinned.
Odoo is an open source suite of integrated business applications: ERP, CRM, accounting, inventory, sales, projects, a website builder, and dozens more, all sharing one database.
Prefer not to run it yourself? Managed Odoo from $13.33/mo
# Odoo 18 in Docker, base pinned by digest docker pull ghcr.io/remarkablecloud/odoo:18.0-r1 docker compose up -d
- Current build
18.0-r1, updated Sep 11, 2026- Base
- Odoo 18 Community official, digest-pinned
- What's inside
- PostgreSQL pairing, addons volume, proxy-aware config, healthcheck
- Upstream license
- Odoo (Community): LGPL-3.0
The image
What our image adds.
What changes from upstream Odoo, and why it matters in production.
Digest-pinned base
Built from odoo:18@sha256:c01e5bc381f0… (Odoo 18.0 Community, Python 3.12). Pinning by digest keeps rebuilds reproducible.
No insecure master password
Odoo's database manager is protected by a master password that upstream leaves at the default admin. Our image generates a strong one on first run, persists it in the filestore volume, and prints it once, so only you can create or drop databases.
PostgreSQL
The connection is configured from HOST / PORT / USER / PASSWORD; Odoo waits for the database before starting.
Persistent filestore
Attachments and sessions live in the /var/lib/odoo volume.
Healthcheck
A container HEALTHCHECK polls /web/health so the platform routes traffic only once Odoo is serving. The current published tag is ghcr.io/remarkablecloud/odoo:18.0-r1.
Run it yourself, or not
Same image either way.
Pull it and run it anywhere, or let us run Odoo for you on a managed server with updates, monitoring and snapshots.
Run Odoo yourself
- Pull it from GHCR and run it on any Docker host
- The guide below: compose, environment, backups, upgrades
- You patch, back up and watch it
Odoo on a managed server
- Installed for you from this same image, $0 for the app
- Updates with a snapshot first, monitoring and a managed firewall
- A 4 GB server from $13.33/mo billed annually, with room for more apps
The guide
Run it in production.
Compose file, environment reference, hardening, backups and upgrades, written by the people who build the image.
On this page
Architecture at a glance
- Odoo serves on port
8069. TLS is terminated upstream by a reverse proxy (Traefik on the RemarkableCloud App Platform). - PostgreSQL is a separate database container; the user Odoo connects with must be able to create databases (the manager creates one per Odoo instance).
- A data volume at
/var/lib/odooholds the filestore (attachments, sessions) and the generated master password.
Docker Compose walkthrough
The standalone stack (Odoo and PostgreSQL) is defined in the image’s docker-compose.yml:
name: odoo
services:
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: odoo
POSTGRES_PASSWORD: ${DB_PASSWORD:-change-me-db}
POSTGRES_DB: postgres
volumes: [db-data:/var/lib/postgresql/data]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U odoo"]
interval: 10s
timeout: 5s
retries: 12
odoo:
image: ${ODOO_IMAGE:-ghcr.io/remarkablecloud/odoo:18.0-r1}
restart: unless-stopped
depends_on:
db:
condition: service_healthy
ports: ["${HTTP_PORT:-8069}:8069"]
environment:
HOST: db
PORT: "5432"
USER: odoo
PASSWORD: ${DB_PASSWORD:-change-me-db}
volumes:
- odoo-data:/var/lib/odoo
volumes:
db-data:
odoo-data:
Step by step:
- The app waits for the database.
depends_onwithcondition: service_healthyavoids a first-boot race against PostgreSQL. - The database user can create databases. The compose uses the Postgres superuser (
POSTGRES_USER), so Odoo’s manager can create the instance database. - You create your database on first access. Open Odoo, use the master password (from the log) in the database manager to create your database, choose the apps you want, and set your admin email and password.
- Only the web port is exposed.
${HTTP_PORT:-8069}:8069is for local use; in production the proxy connects to port8069on the internal network. - State lives in volumes.
odoo-data(/var/lib/odoo) anddb-datapersist across restarts and upgrades.
To start it locally:
DB_PASSWORD=$(openssl rand -hex 16) docker compose up -d
Then read the master password from docker compose logs odoo, open http://localhost:8069, and create your database.
Environment variable reference
These are wired automatically by the App Platform backend from the managed PostgreSQL; they are listed here for standalone and self-hosted runs.
| Variable | Required | Value / default | Purpose |
|---|---|---|---|
HOST | yes | <db_host> | PostgreSQL host. |
PORT | no | 5432 | PostgreSQL port. |
USER | yes | <db_user> | PostgreSQL user (must be able to create databases). |
PASSWORD | yes | <db_password> | PostgreSQL password. |
The master password (admin_passwd) is generated on first run and stored in the data volume; it is not an environment variable.
Hardening notes
- Strong master password. The database manager is never left at the insecure
admindefault; a generated master password is required to create or drop databases. - No baked credentials. The master password is generated at runtime and stored only in the data volume.
- Digest-pinned base. Each build is auditable and reproducible.
- Healthcheck gates traffic.
/web/healthmust return success before the platform routes requests. - Keep PostgreSQL private. Do not publish its port to the host or the internet.
- After creating your database, you can further harden by disabling the database manager (
list_db = False) once you no longer need to create databases.
Backups
Capture the database and the data volume together:
- The PostgreSQL database (use your Odoo database name):
docker compose exec db pg_dump -U odoo <your-odoo-db> > odoo-db.sql - The data volume at
/var/lib/odoo(filestore: attachments, sessions):docker run --rm -v odoo_odoo-data:/data -v "$PWD":/backup alpine \ tar czf /backup/odoo-data.tgz -C /data .
Odoo also has a built-in backup in the database manager (database + filestore in one zip). On the RemarkableCloud App Platform, database and volume backups follow the platform’s backup schedule.
Upgrades
- New builds ship as new
-rtags. Pull the new tag and recreate the container; Odoo applies module updates on start when needed:docker compose pull odoo && docker compose up -d odoo - Major Odoo version upgrades (for example 18 to 19) are done with Odoo’s upgrade process, not a simple image swap; read the upstream upgrade notes first.
- Back up first, and keep the database dump and the
/var/lib/odooarchive from just before the upgrade. - Read the changelog. Every build is listed in
CHANGELOG.mdwith the base image digest and any behavior changes.
Changelog
Each build is pinned by digest and recorded here, so you can see what changed before you pull a new tag.
-
18.0-r1Current Sep 11, 2026
Odoo and other product names are trademarks of their respective owners. RemarkableCloud is not affiliated with or endorsed by them.
FAQ
Odoo 18 in Docker, answered.
Short answers from the people who build and run this image.
Do I need a database?
Yes. Odoo stores everything in PostgreSQL. The standalone compose file includes it, using the superuser so Odoo's manager can create the instance database.
What is the master password?
It protects Odoo's database manager (create, duplicate, drop, backup). The image generates a strong one on first run and prints it once to the container log; you use it to create your database.
How do I set my admin login?
When you create your database in the manager, you set the admin email and password there; that is your day-to-day login (separate from the master password).
How does HTTPS work if the container serves HTTP on 8069?
TLS is terminated at the reverse proxy (Traefik on the App Platform), which forwards to port 8069 on the internal network.
Which tag should I run?
Use the current pinned tag, ghcr.io/remarkablecloud/odoo:18.0-r1. Avoid moving tags so a redeploy cannot change the image under you.
Pull it, or let us run it.
The same image runs Odoo on our managed servers, updates and monitoring included.