| title | Odoo Docker Image |
|---|---|
| category | Guide |
| description | Documentation for the Odoo Docker image and deployment. |
| context | Project Root |
| maintainer | ryumada |
A Dockerfile to create a custom Odoo docker image.
| Specification | Version |
|---|---|
| Host OS | Ubuntu 22.04 / Debian 12 / CentOS 8-9 Stream (Linux) |
| Python | '3.7' (recommended) or '3.10' |
| Odoo version | '16,17,18,19' (tested) |
| PostgreSQL | '14' (tested), and '15, 16, 17' (requires matching POSTGRESQL_VERSION in .env to the host version) |
| Python '3.10' has slower build time and not compatible with ks_dashboard.
|
Install the required packages on your host machine before running setup.sh.
⚠️ The Docker container always uses a Debian-based image regardless of host OS — these packages are for the host only.
Debian / Ubuntu
sudo apt update
sudo apt install -y docker.io docker-compose-plugin logrotate postgresqlCentOS 8 / 9 Stream
# Install Docker CE
sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
sudo systemctl enable --now docker
# Install Logrotate and PostgreSQL
sudo dnf install -y logrotate postgresql-server
sudo postgresql-setup --initdb
sudo systemctl enable --now postgresqlSELinux Note: If Docker bind-mounts to
/var/lib/odooor/var/log/odoofail with permission errors, relabel those directories:sudo chcon -R -t container_file_t /var/lib/odoo /var/log/odooAlternatively, allow Docker to use SELinux labels via volume options in
docker-compose.yml:volumes: - /var/lib/odoo:/var/lib/odoo:z
There are some points you should know:
-
First, you need to execute
sudo ./setup.shscript to check if all of your files and directories are ready and to configure the deployment mode.sudo ./setup.sh
⚠️ When asked, select the deployment mode:- 1. Development: Builds locally. Uses bind-mounts for
odoo-baseandgitdirectories to allow real-time code changes. - 2. Builder: Builds the image, tags it, and prepares it for pushing to a registry. Includes bind-mounts for verification.
- 3. Production: Pulls the pre-built image from the configured registry. No bind-mounts for code.
- 1. Development: Builds locally. Uses bind-mounts for
-
Configuration: Check the
.envfile for important variables, especially:DOCKER_BUILD_MODE: 1=Dev, 2=Builder, 3=Prod.ODOO_IMAGE_NAME: Image name (e.g.,ghcr.io/username/project).CURRENT_IMAGE_VERSION and NEXT_IMAGE_VERSION: Image tag (e.g.,16.0-v1).ODOO_IMAGE_SOURCE: Source git repo (for GHCR labels).
-
[
Odoo Base] You should add your Odoo base, whether it is Odoo Community, Odoo Enterprise, or your custom Odoo base, to theodoo-basedirectory (⚠️ Only add one directory toodoo-baseas this will be read automatically by theentrypoint.shscript, for the name of the directory is no need to beodoo⚠️ ). -
[
Extra Addons/Modules] Add your custom Odoo Modules (Odoo Addons) togitdirectory and add the path to addons_path in./conf/odoo.conf. Don't add unused custom module directory to this directory as it will be added to your docker image and increased the image size.⚠️ If your path is in./git/odoo-custom-modules, then your addons_path should be/opt/odoo/git/odoo-custom-modules.⚠️ If you have subdirectory inside your git addons repository path it should be like this:/opt/odoo/git/odoo-custom-modules/subdir-1/opt/odoo/git/odoo-custom-modules/subdir-2
-
[
Odoo Static Data] Odoodatadiris placed on/var/lib/odooand Odoologis placed on/var/log/odoo. These directories will be used by Odoo for static data storage and logging. It will be called in docker-compose (⚠️ These directories are automatically created on your host machine after you runsudo ./setup.sh⚠️ ). -
Build and Runyour odoo deployment.Development / Builder Mode:
docker compose up -d --build
Production Mode:
docker compose pull docker compose up -d
-
If your Odoo module needs libreoffice either:
- Set
INSTALL_LIBREOFFICE=Yin.env. - Or run:
docker exec -itu root $CONTAINER_ID apt --no-install-recommends -y install libreoffice
- Set
-
Container Registry Workflow:
Pushing to Container Registry
- Set
DOCKER_BUILD_MODE=2(or select Builder mode insetup.sh). - Set
ODOO_IMAGE_NAME,CURRENT_IMAGE_VERSION and NEXT_IMAGE_VERSION, andODOO_IMAGE_SOURCEin.env. - Login to your registry:
docker login ghcr.io -u <username> -p <token>
- Build and Push:
docker compose build docker compose push
- Set
The image build using the dockerfile in this repository installed some utility scripts.
You can check the Odoo version and its git hash by running this command:
docker compose exec $SERVICE_NAME getinfo-odoo_baseYou can get $SERVICE_NAME by running docker compose ps in your root repository where docker compose file located.
This is the output of the command:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-odoo-odoo-1 docker-odoo:latest "/opt/odoo/entrypoin…" odoo 2 minutes ago Up 2 minutesAs you can see in the SERVICE column, the service name is odoo.
You can check the git repository information by running this command:
docker compose exec $SERVICE_NAME getinfo-odoo_git_addonsYou can get $SERVICE_NAME by running docker compose ps in your root repository where docker compose file located.
This is the output of the command:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-odoo-odoo-1 docker-odoo:latest "/opt/odoo/entrypoin…" odoo 2 minutes ago Up 2 minutesAs you can see in the SERVICE column, the service name is odoo.
Odoo shell has been created automatically after you run sudo ./setup.sh script. The shell is copied when the image is built. You can run the Odoo shell by running this command:
# See help to see how to use the shell
docker compose exec $SERVICE_NAME odoo-shell help
# example command to run shell with service_name odoo
docker compose exec odoo odoo-shell example_database_nameYou can get $SERVICE_NAME by running docker compose ps in your root repository where docker compose file located.
This is the output of the command:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-odoo-odoo-1 docker-odoo:latest "/opt/odoo/entrypoin…" odoo 2 minutes ago Up 2 minutesAs you can see in the SERVICE column, the service name is odoo.
Odoo Module Upgrade tool also has been created automatically after you run sudo ./setup.sh. The tool is copied when the image is built. You can run the tool by running one of these command examples:
# See help to see how to use the tool
docker compose exec $SERVICE_NAME odoo-module-upgrade help
# example command to update odoo modules
## update single module
docker compose exec odoo odoo-module-upgrade example_database_name --update=module_name
## update multiple modules (Be careful with module that need to install in order)
docker compose exec odoo odoo-module-upgrade example_database_name --update=module_name1,module_name2
## update all modules (⚠️ This command is not recommended to use in production ⚠️)
docker compose exec odoo odoo-module-upgrade example_database_name --update=allYou can get $SERVICE_NAME by running docker compose ps in your root repository where docker compose file located.
This is the output of the command:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-odoo-odoo-1 docker-odoo:latest "/opt/odoo/entrypoin…" odoo 2 minutes ago Up 2 minutesAs you can see in the SERVICE column, the service name is odoo.
If you setup this variable in .env:
...
# # # # # # # # # # # # # # # #
# VSCODE ON Container #
# # # # # # # # # # # # # # # #
# Set the direct download URL of vscode for debian to install vscode inside your odoo container
# possible values
VSCODE_DIRECT_DOWNLOAD_URL=
...Then, vscode will be installed inside the container when you build the image. Here how to activate vscode from your container:
# This will open the vscode web on http://localhost:8000
docker compose exec $SERVICE_NAME code serve-web
# You can change the port of vscode if port 8000 is already in use
docker compose exec $SERVICE_NAME code serve-web --port
# See help of code cli
docker compose exec $SERVICE_NAME code serve-web --helpYou can get $SERVICE_NAME by running docker compose ps in your root repository where docker compose file located.
This is the output of the command:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
docker-odoo-odoo-1 docker-odoo:latest "/opt/odoo/entrypoin…" odoo 2 minutes ago Up 2 minutesAs you can see in the SERVICE column, the service name is odoo.
By default, docker-odoo assumes PostgreSQL is running natively on the host machine. However, it fully supports connecting to remote PostgreSQL servers or containerized database instances (e.g., another Docker container like docker-postgresql).
- Open up your
.envfile. - Change
DB_HOSTfromlocalhostto the target IP address, domain name, or Docker container name (e.g.,docker-postgresql-postgres-1). - Set
DOCKER_NETWORK_MODEto the name of the Docker network shared between Odoo and your target database (e.g.,db-net).
When setup.sh detects a non-local DB_HOST, it skips local database provisioning. Instead, it securely generates a strong PostgreSQL username and password, saving them into your local .secrets/ directory.
The setup script will then print a precise CREATE ROLE SQL command to your terminal. Simply copy and execute this command manually within your target PostgreSQL instance to grant Odoo the necessary authenticated access!
Note: All auxiliary tools (such as scripts/example/restore_backupdata.sh.example and databasecloner.sh.example) dynamically adapt to remote targets by spinning up lightweight docker run --rm postgres query runners to execute cross-network SQL commands safely, avoiding the need for host credentials!
Deploying Odoo securely over the web with automated SSL generation and isolated internal traffic is strongly recommended. docker-odoo supports both NGINX and Traefik workflows out of the box.
If you are using Traefik, the setup.sh script will automatically map routing paths (including Longpolling and WebSockets logic for Odoo 16+) and mount all the necessary Docker labels onto your deployment!
- Open up your
.envfile. - Ensure you have the following variables populated:
# Choose your reverse proxy type (NGINX or Traefik)
REVERSE_PROXY_TYPE=traefik
# Set the domain here
TRAEFIK_DOMAIN=odoo.yourdomain.com
# Set the Let's Encrypt / TLS resolver name configured in your Traefik instance
TRAEFIK_CERTRESOLVER=letsencrypt- Ensure you have properly bound your Traefik proxy network so the containers can communicate locally.
# Point this to your Traefik web network name
DOCKER_NETWORK_MODE=proxy- Simply run
sudo ./setup.sh! - The
docker-compose.ymlfile is immediately generated with fully baked isolation routing forodoo.yourdomain.comtargeting both Standard HTTP traffic andPathPrefix(\/websocket`)` longpolling traffic concurrently!
Copyright © 2024 ryumada. All Rights Reserved.
Licensed under the MIT license.