Dockerized environment to ease odoo development
Odoo developers who want to install and manage Odoo instances quickly, consistently, and without knowing Docker internals. Also useful for anyone deploying multiple Odoo projects with different versions on the same machine.
Odoo-env is a CLI tool (oe) that manages Docker-based Odoo environments. It reads
an Odoo module manifest to understand everything about a deployment — repositories,
Docker images, configuration — so a single manifest completely defines a project.
__manifest__.pyoe -i git@github.com:org/project.git clones the repo,
discovers the manifest automatically, and sets up the entire directory structure-codoo-net is created automatically on
first use~/.config/oe/oe_config.yaml# Install
pipx install odoo-env
# Install a project from its repository
oe -i git@github.com:your-org/your-project.git -c yourclient
# Pull images and extract sources for debug
oe -p -i
# Start the environment
oe -R -r
# Update modules
oe -u
# Restore latest backup
oe --restore
| Command | Description |
|---|---|
-i [URL] |
Install environment. If a URL is given, clones the repo and auto-discovers the project name from the manifest. Without URL, updates all repositories for the configured client. |
-p |
Pull all Docker images declared in the client manifest. In debug mode, also extracts Odoo sources to the host. |
-w |
Create / overwrite the odoo.conf file from manifest config. |
| Command | Description |
|---|---|
-R |
Run environment containers: postgres, wdb (debug mode), aeroo (old Odoo versions). |
-r |
Run Odoo container. Detached in prod, interactive in debug. |
-S |
Stop environment containers. |
-s |
Stop Odoo container. |
| Command | Description |
|---|---|
-u |
Update modules. Use -m module for specific modules, or omit for all. Use -d database for non-default databases. |
-I module |
Install a module into the client database (comma-separated for several). New modules are installed with -i; modules already installed are updated with -u instead of reinstalled. Use -d database for non-default databases. |
--restore |
Restore a backup into the client database. By default restores the newest .zip in backup_dir. Use -f for a specific file, -d for a target database. |
--no-deactivate |
Skip database deactivation before restore. Deprecated. |
--create-test-db |
Create a [client]_test database: restores the test seed, then installs every module found in the repository. |
| Command | Description |
|---|---|
-Q sale,stock |
Run Odoo tests on comma-separated module list. Uses the [client]_test database with admin/admin credentials. Add -d database to override. |
| Command | Description |
|---|---|
-c CLIENT |
Set the default client name. Persistent — saved in config. |
-d DATABASE |
Set the default database name. Persistent. |
--debug |
Set environment to debug mode. Persistent. |
--prod |
Set environment to production mode. Persistent. |
--base-dir PATH |
Set root directory for all environments (e.g. /odoo_ar/). Persistent. Does not require a client to be configured. |
--deploy-keys |
(Prod mode only) Generate SSH deploy key pairs for every private repository in the manifest. Prints public keys for adding to GitHub/GitLab. |
| Command | Description |
|---|---|
-H |
Show odoo --help from the Odoo image declared in the manifest. |
-V |
Show odoo-env version and exit. |
-v |
Verbose mode — prints every command before execution. |
/odoo_ar/ # --base-dir (default)
└── odoo-18.0/ # version + optional 'e' for Enterprise
└── clientname/
├── config/ # odoo.conf
├── data_dir/ # Odoo filestore
├── backup_dir/ # .zip backups for --restore
├── log/ # odoo.log
├── postgresql/ # PostgreSQL data volume
└── sources/ # cloned git repositories
├── src/ # Odoo core sources (debug, v11-v18)
├── site-packages/ # venv packages (debug, v19+)
└── lib/ # python libs (debug, v11-v18)
| Odoo | Python | Special notes |
|---|---|---|
| 8 – 10 | 2.7 | Uses dist-packages, extra-addons |
| 11 – 12 | 3.5 – 3.7 | Uses dist-packages |
| 13 | 3.7 | |
| 14 – 16 | 3.9 | Uses src + lib mounts |
| 17 | 3.10 | Uses src + lib mounts |
| 18 | 3.12 | Uses src + lib mounts |
| 19 | 3.10 (venv) | Uses odoo-bin, src + site-packages |
Docker images are hosted at Docker Hub and Dockerfiles at GitHub.
The manifest is a standard Odoo __manifest__.py with extra keys that only odoo-env
reads. Odoo itself ignores them, so the module remains installable.
Required keys:
name, version (standard Odoo)env-ver: '2' (must be exactly ‘2’)git-repos — list of repositories to clonedocker-images — list of Docker images to pullOptional keys:
odoo-license — 'CE' (default) or 'EE'config — production odoo.conf parametersconfig-local — debug mode odoo.conf parametersport — Odoo HTTP port (default 8069)longpolling_port — longpolling port (default 8072)prod_server — SSH alias for scp backup transferexternal_dependencies — system packagesSee the full manifest example below.
Author: Jorge Obiols jorge.obiols@gmail.com
What you need to know:
The manifest holds:
version keyword (e.g. 18.0.1.0.0 → branch 18.0)'2'odoo.conf (prod vs debug)'CE' (Community, default) or 'EE' (Enterprise)--restore workflows that involve SCP)As a best practice, list all required modules in the depends key. Then the project not only
installs the environment but also documents which modules are needed. Run oe -u to install
them all in one shot — it runs odoo-bin --update all --stop-after-init inside the container.
git-reposGeneral syntax: <repo-url> [<target-dir>[/<subdir>]] [-b <branch>]
Odoo-env automatically determines the branch from the Odoo version in the manifest
(e.g. version: '18.0.1.0.0' → branch 18.0). Override with -b when a repo doesn’t
follow this convention.
Basic example:
'git-repos': [
'https://github.com/OCA/account-invoicing.git',
'https://github.com/OCA/account-financial-tools.git',
]
Tree:
sources/
├── account-invoicing/
└── account-financial-tools/
Renaming to avoid collisions:
'git-repos': [
'https://github.com/OCA/account-invoicing.git oca-account-invoicing',
'https://github.com/ingadhoc/account-invoicing.git adhoc-account-invoicing',
]
Tree:
sources/
├── oca-account-invoicing/
└── adhoc-account-invoicing/
Single-module repos (nesting):
'git-repos': [
'https://github.com/ctmil/meli_oerp.git ctmil/meli_oerp',
]
Tree:
sources/
└── ctmil/
└── meli_oerp/
Custom branch override:
'git-repos': [
'https://github.com/ctmil/odoo_barcode.git ctmil/odoo_barcode -b main',
]
SSH protocol (uses your SSH keys):
'git-repos': [
'git@github.com:jobiols/private-repo.git private-repo -b 18.0',
]
docker-imagesSyntax: <short-name> <image:tag>
The short-name is how odoo-env refers to the image internally.
odoo, postgres, aeroo, and nginx are recognized names.
'docker-images': [
'odoo jobiols/odoo-jeo:18.0',
'postgres postgres:17.5-alpine',
]
{
'name': 'myproject',
'version': '18.0.1.0.0',
'category': 'Tools',
'summary': 'Example project for Odoo 18 CE',
'author': 'jeo Software',
'website': 'https://github.com/jobiols/odoo-env',
'license': 'AGPL-3',
'depends': [
'sale_management',
'account',
],
'installable': True,
'application': False,
# ---------- odoo-env manifest (env-ver: 2) ----------
'env-ver': '2',
# Community or Enterprise
'odoo-license': 'CE',
# HTTP port
'port': '8069',
# Production server SSH alias (for backup transfer)
'prod_server': 'ubuntu@my-server',
# ---------- odoo.conf for production ----------
'config': [
'workers = 4',
'max_cron_threads = 1',
'limit_request = 8192',
'limit_memory_soft = 2147483648',
'limit_memory_hard = 2684354560',
'limit_time_cpu = 60',
'limit_time_real = 120',
'admin_passwd = my-secure-password',
'dbfilter = myproject',
'db_maxconn = 64',
'log_level = info',
'logfile = /var/log/odoo/odoo.log',
],
# ---------- odoo.conf for debug ----------
'config-local': [
'admin_passwd = admin',
# In debug mode, workers/max_cron_threads/limit_time_* are
# forced to 0 automatically by odoo-env.
],
# ---------- Repositories ----------
'git-repos': [
'https://github.com/OCA/web.git oca-web',
'https://github.com/OCA/server-tools.git oca-server-tools',
'https://github.com/ingadhoc/odoo-argentina.git adhoc-odoo-argentina',
'git@github.com:myorg/private-modules.git private-modules -b 18.0',
],
# ---------- Docker images ----------
'docker-images': [
'odoo jobiols/odoo-jeo:18.0',
'postgres postgres:17.5-alpine',
],
# ---------- External system dependencies ----------
'external_dependencies': {
'python': ['requests', 'openpyxl'],
},
}
Odoo-env stores its own configuration at ~/.config/oe/oe_config.yaml:
base_dir: /odoo_ar/
client: myproject
environment: debug
last_version_check: '2026-05-23'
clients:
- myproject: /odoo_ar/odoo-18.0/myproject/sources/cl-myproject/myproject
- otherproj: /odoo_ar/odoo-16.0e/otherproj/sources/cl-otherproj/otherproj
base_dir — root where all environments live (default /odoo_ar/). On macOS,
set this to a path inside your home directory.client — the currently active client name.environment — debug or prod.clients — maps each client name to the path of its __manifest__.py directory.
Odoo-env discovers and saves this automatically.last_version_check — date of last PyPI version check.Pre-built Odoo images for all Community versions from 8.0 to 19.0 are hosted on Docker Hub.
The Dockerfiles to build these images (or create your own) are at github.com/jobiols/docker-odoo-jeo.
You are encouraged to fork the repo and customize images for your needs.
| Odoo version | Odoo image tag | Postgres | WDB image |
|---|---|---|---|
| 8.0 | jobiols/odoo-jeo:8.0 |
postgres:9.6-alpine |
kozea/wdb |
| 9.0 | jobiols/odoo-jeo:9.0 |
postgres:9.6-alpine |
kozea/wdb |
| 10.0 | jobiols/odoo-jeo:10.0 |
postgres:9.6-alpine |
kozea/wdb |
| 11.0 | jobiols/odoo-jeo:11.0 |
postgres:10.1-alpine |
kozea/wdb |
| 12.0 | jobiols/odoo-jeo:12.0 |
postgres:10.1-alpine |
kozea/wdb |
| 13.0 | jobiols/odoo-jeo:13.0 |
postgres:10.1-alpine |
kozea/wdb |
| 14.0 | jobiols/odoo-jeo:14.0 |
postgres:13-alpine |
kozea/wdb |
| 15.0 | jobiols/odoo-jeo:15.0 |
postgres:13-alpine |
kozea/wdb |
| 16.0 | jobiols/odoo-jeo:16.0 |
postgres:13-alpine |
jobiols/wdb:3.3.1 |
| 17.0 | jobiols/odoo-jeo:17.0 |
postgres:17.5-alpine |
jobiols/wdb:3.3.2 |
| 18.0 | jobiols/odoo-jeo:18.0 |
postgres:17.5-alpine |
jobiols/wdb:3.3.2 |
| 19.0 | jobiols/odoo-jeo:19.0 |
postgres:17.5-alpine |
jobiols/wdb:3.3.2 |
Note: For Odoo 19+, the entrypoint changes from
odoo.pytoodoo-bin.
| Image | Purpose | Notes |
|---|---|---|
aeroo |
Aeroo reports engine | Only used for Odoo ≤ 9. Can be omitted for newer versions. |
dbtools |
Database backup/restore tools | jobiols/dbtools:1.3.1 — used internally by backup operations. |
/var/lib/postgresql/18/docker. Odoo-env handles this automatically.pg-<clientname> and connected to the odoo-net
Docker network as db.In the manifest docker-images list, each entry is a pair:
'short-name image:tag'
The short-name tells odoo-env which role the image plays. Recognized names:
odoo, postgres, aeroo, nginx.
Example:
'docker-images': [
'odoo jobiols/odoo-jeo:18.0',
'postgres postgres:17.5-alpine',
]
In debug mode, odoo-env automatically pulls the debug variant of the Odoo image (if available) and extracts sources to the host. In production mode, it pulls the standard image.
This example uses Ubuntu Server 24.04 LTS. Adapt for your distribution.
# Upgrade the system
sudo apt update && sudo apt upgrade -y
# Install pipx (recommended way to install odoo-env)
sudo apt install pipx -y
pipx ensurepath
# Install odoo-env
pipx install odoo-env
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
rm get-docker.sh
# Add your user to the docker group (log out and back in afterwards)
sudo usermod -aG docker $USER
# Verify tools
oe -V
docker --version
You need an Odoo module with an extended manifest. The simplest approach is to keep it in a git repository so you can install with a single command.
Minimal manifest (__manifest__.py):
{
'name': 'myproject',
'version': '18.0.1.0.0',
'category': 'Tools',
'summary': 'My Odoo 18 project',
'author': 'jeo Software',
'license': 'AGPL-3',
'depends': [],
'installable': True,
'application': False,
'env-ver': '2',
'git-repos': [
'https://github.com/OCA/web.git',
],
'docker-images': [
'odoo jobiols/odoo-jeo:18.0',
'postgres postgres:17.5-alpine',
],
}
You can install from a local repo or directly from a remote URL:
# Option A: Install from a remote repository (auto-discovers project name)
oe -i git@github.com:your-org/myproject.git -c myproject
# Option B: If you already have the repo cloned locally
cd /path/to/myproject
oe -i -c myproject
This creates the directory structure under --base-dir (default /odoo_ar/):
/odoo_ar/
└── odoo-18.0/
└── myproject/
├── config/
├── data_dir/
├── backup_dir/
├── log/
├── postgresql/
└── sources/
└── web/
Note: After installation, the original cloned repo can be deleted — the working copy lives in
sources/.
# Set debug mode
oe --debug
# Pull Docker images and extract Odoo sources to the host
oe -p -i
# Write the odoo.conf
oe -w
# Start the environment (postgres + wdb debugger) and Odoo
oe -R -r
Odoo starts in interactive mode with WDB attached. Open http://localhost:8069 in your browser
and create a database. The default master password in debug mode is admin.
# Set production mode
oe --prod
# Install, pull images, start
oe -i -p -w
oe -R -r
In production, Odoo runs detached with optimized worker settings. Workers and cron threads are calculated automatically from CPU count unless overridden in the manifest.
# Restart Odoo
oe -s -r
# Stop everything
oe -S
# Start everything again
oe -R -r
# Update all repositories
oe -i
# Pull latest Docker images
oe -p
# Update all modules in the database
oe -u
# Update a specific module
oe -u -m sale
# Restore the latest backup
oe --restore
# Restore a specific backup file
oe --restore -f backup_2025_01_15.zip
# Restore to a different database
oe --restore -d myproject_test
# Generate deploy keys for private repos (production only)
oe --prod --deploy-keys
# Switch between projects
oe -c otherproject
# Run tests
oe -Q sale,stock -d myproject_test
# Show Odoo help from the container
oe -H
# Verbose mode — see every command
oe -v -R
Odoo-env automatically checks PyPI for newer versions once per day and warns you if an update is available.
pipx upgrade odoo-env
Everything that is persistent is stored in ~/.config/oe/oe_config.yaml. You generally
don’t need to edit it by hand — odoo-env manages it automatically.
base_dir: /odoo_ar/
client: myproject
environment: debug
last_version_check: '2026-05-23'
clients:
- myproject: /odoo_ar/odoo-18.0/myproject/sources/cl-myproject/myproject_default
To change the root directory on systems where /odoo_ar/ doesn’t work (e.g. macOS):
oe --base-dir /Users/you/odoo_ar/