Skip to content

feat: publish a hardened Odoo 20 image that runs on hosted platforms - #1

Merged
gustavovalverde merged 9 commits into
mainfrom
odoo-20
Oct 17, 2026
Merged

gustavovalverde merged 9 commits into
mainfrom
odoo-20

Conversation

@gustavovalverde

Copy link
Copy Markdown

Upstream dockerdoo publishes no Odoo 19 or 20 image, and its runtime image ships passwordless sudo, the master password my-weak-password, and an open database manager. This branch builds on the upstream maintenance stack (iterativo-git#180, iterativo-git#181, iterativo-git#179) and makes the image usable on Railway, Render, and similar platforms without a wrapper image.

Image. The published production target has no sudo or developer tools, no default master password, and LIST_DB=False by default. It adds packaging, which Odoo 20 needs to install add-ons that pin dependency versions. Because it installs Odoo's own requirements, it carries cryptography 42.0.8 and pyOpenSSL 24.1.0. A development target keeps sudo and the debugging tools.

Start-up. A container started as root, which platforms with root-owned volumes require, takes ownership of its data directories and drops to odoo. The server follows the platform's PORT, serves only DBNAME, waits for PostgreSQL, and can create a restricted application role from DB_ADMIN_URL, because Odoo refuses to run as postgres. AUTO_INIT creates the database and installs INIT_MODULES. AUTO_UPGRADE upgrades modules whose manifest version changed and stops the container before serving if an upgrade fails. Both run under an advisory lock, so containers started together apply changes once.

Publication. CI builds only Odoo 20, for amd64 and arm64. It runs the existing runtime tests plus a new hosted-platform test, then publishes ghcr.io/indexa-labs/dockerdoo:20.0, 20.0-YYYYMMDD, and 20.0.YYYYMMDD with a build provenance attestation. The dated semver tag lets platforms that auto-update by semver move between builds of one series. Docker Hub publication and the 18.0 and 19.0 images are dropped from this fork.

Compatibility. Deployments that relied on the old defaults must now set ADMIN_PASSWORD and LIST_DB=True explicitly. A plain docker build . now produces the development target; docker-compose.yml builds production.

The production stage no longer ships passwordless sudo, editors, SSH or
debugging packages, has no default master password, and lists no
databases by default. It adds the packaging module that Odoo needs to
check versioned add-on dependencies. A development stage keeps sudo and
the tools for local work.
A container started as root takes ownership of its data directories and
drops to the odoo user. The server listens on PORT when HTTP_PORT is not
set, serves only DBNAME unless a filter is given, and uses a random
master password when none is set.

Before the server starts, the entrypoint waits for PostgreSQL, can
create a restricted application role from DB_ADMIN_URL, and, when asked,
creates the database, installs INIT_MODULES and upgrades modules whose
manifest version changed. Database changes run under an advisory lock so
containers started together apply them once.
Builds the current 20.0 branch for amd64 and arm64, runs the runtime and
hosted-platform tests, and publishes 20.0, a dated tag and a dated semver
tag with a build provenance attestation.
CI runners use a different uid than the image, and mkdtemp creates
private directories. Upload the hosted-test logs on failure.
@gustavovalverde
gustavovalverde merged commit 09829dd into main Oct 17, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant