From 7dc3fd052bdf7029bbe9ebbeacf8c085ec84b4be Mon Sep 17 00:00:00 2001 From: Janik von Rotz Date: Mon, 20 Apr 2026 10:39:44 +0200 Subject: [PATCH] feat(odoo): support loading db credentials from files and enhance Python package management with requirements.txt --- compose.yml.template | 11 ++++++++- images/odoo/CHANGELOG.md | 26 ++++++++++++++++++-- images/odoo/Dockerfile | 16 ++++++------- images/odoo/README.md | 23 ++++++++++++++---- images/odoo/bin/{conf => config} | 0 images/odoo/bin/install-python-packages | 32 +++++++++++++++---------- images/odoo/entrypoint.sh | 11 ++++++--- task | 17 ++++++++++--- 8 files changed, 102 insertions(+), 34 deletions(-) rename images/odoo/bin/{conf => config} (100%) diff --git a/compose.yml.template b/compose.yml.template index ccb7dc3d..17608188 100644 --- a/compose.yml.template +++ b/compose.yml.template @@ -13,7 +13,6 @@ services: PORT: 5432 PGHOST: db PGUSER: odoo - PGPASSWORD: odoo PGPORT: 5432 DB_NAME: "${DB_NAME}" DB_MAXCONN: ${DB_MAXCONN} @@ -76,6 +75,11 @@ services: TEST_EXCLUDE: ${TEST_EXCLUDE} AUTO_UPDATE_TRANSLATIONS: "${AUTO_UPDATE_TRANSLATIONS}" AUTO_UPDATE_MODULES_LIST: "${AUTO_UPDATE_MODULES_LIST}" + #db_user_FILE: /run/secrets/db_user + #db_password_FILE: /run/secrets/db_password + secrets: + - db_user + - db_password command: ${ODOO_COMMAND} ports: - "${ODOO_PORT}:8069" @@ -159,3 +163,8 @@ volumes: networks: default: name: odoo-build_default +secrets: + db_user: + file: ./tmp/db_user.txt + db_password: + file: ./tmp/db_password.txt \ No newline at end of file diff --git a/images/odoo/CHANGELOG.md b/images/odoo/CHANGELOG.md index 087da482..443021ad 100644 --- a/images/odoo/CHANGELOG.md +++ b/images/odoo/CHANGELOG.md @@ -2,10 +2,32 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). -## Undefined +## [Unreleased] + +### Added + +- Support for installing Python packages from `/var/lib/odoo/requirements.txt` via `install-python-packages` script. +- Documentation for `requirements.txt` and updated paths in `README.md` to reflect new virtual environment locations. +- New virtual environment path `/var/lib/odoo/venv` for additional Python packages. +- Support for loading database credentials from files via `db_user_FILE` and `db_password_FILE` environment variables. +- Added `secrets` section in `compose.yml.template` to support loading database credentials from files. + +### Changed + +- Renamed virtual environment path from `/opt/odoo-venv` to `/opt/odoo/venv` and `/var/lib/odoo/venv` for better separation of Odoo tools and user-installed packages. +- Updated `Dockerfile` to use `/var/lib/odoo/venv` for additional Python packages and adjusted `PATH` accordingly. +- Modified `install-python-packages` to check PyPI availability before installing packages and to install from `requirements.txt` if present. +- Updated `install-python-packages` to use `--no-deps` flag for both `PYTHON_INSTALL` and `requirements.txt` installations. +- Adjusted directory permissions in `Dockerfile` to exclude `/opt/odoo-venv` since it no longer exists. +- Updated `README.md` to reflect new paths and behavior for Python package installation. +- Updated `entrypoint.sh` to support loading database credentials from files via `_FILE` environment variables. +- Renamed `bin/conf` to `bin/config` for consistency. +- Updated `task` script to reflect correct test description for `test-xmlrpc` (now "Test xml rpc connection"). ### Fixed +- Fixed test in `task` script to verify `click` is installed in `/var/lib/odoo/venv/` when using `requirements.txt`. + ## 2026-01-29 ### Added @@ -24,7 +46,7 @@ All notable changes to this project will be documented in this file. The format - Inconsistent naming of `DBFILTER` is now `DB_FILTER`. - Remove `-e` from Odoo pip install. -## Removed +### Removed - Removed the `AUTO_UPDATE_MODULES` env var. - Removed the `ODOO_DATABASE` env var. diff --git a/images/odoo/Dockerfile b/images/odoo/Dockerfile index b5aec32c..fb4e8e84 100644 --- a/images/odoo/Dockerfile +++ b/images/odoo/Dockerfile @@ -31,12 +31,12 @@ RUN apt-get update && \ COPY --from=ghcr.io/astral-sh/uv:0.7.21 /uv /uvx /bin/ # Prepare virtual env -RUN uv venv /opt/odoo-venv -ENV PATH=/opt/odoo-venv/bin:$PATH +RUN uv venv /opt/odoo/venv +ENV PATH=/opt/odoo/venv/bin:$PATH # Install Odoo tools -COPY ./images/odoo/requirements.txt /opt/odoo-venv/ -RUN uv pip install --no-cache-dir -r /opt/odoo-venv/requirements.txt +COPY ./images/odoo/requirements.txt /opt/odoo/venv/ +RUN uv pip install --no-cache-dir -r /opt/odoo/venv/requirements.txt # Install Odoo COPY ./odoo /opt/odoo @@ -142,12 +142,14 @@ RUN pnpm install -g rtlcss # Install uv for Python package management COPY --from=ghcr.io/astral-sh/uv:0.7.21 /uv /uvx /bin/ +# Prepare virtual env for custom packages +RUN uv venv /var/lib/odoo/venv + # Copy the virtual environment and Odoo from the builder stage -COPY --from=builder /opt/odoo-venv /opt/odoo-venv COPY --from=builder /opt/odoo /opt/odoo # Setup environment path -ENV PATH=/opt/odoo-venv/bin:$PATH +ENV PATH=/var/lib/odoo/venv/bin:/opt/odoo/venv/bin:$PATH ENV ADDONS_PATH=/opt/odoo/addons ENV PYTHONPATH=/opt/odoo/ @@ -162,7 +164,6 @@ WORKDIR /opt/odoo # Setup folder and permissions: # Config: /etc/odoo # Data: /var/lib/odoo -# Python: /opt/odoo-venv # Addons: /mnt/extra-addons RUN mkdir -p /var/lib/odoo \ && mkdir -p /mnt/extra-addons @@ -170,7 +171,6 @@ RUN mkdir -p /var/lib/odoo \ # Set OpenShift compatible permissions - Make directories writable by any user ID RUN chmod -R 775 /etc/odoo \ /var/lib/odoo \ - /opt/odoo-venv \ /mnt/extra-addons # Nginx configuration diff --git a/images/odoo/README.md b/images/odoo/README.md index 4e0a518e..55154bae 100644 --- a/images/odoo/README.md +++ b/images/odoo/README.md @@ -169,6 +169,11 @@ services: AUTO_UPDATE_MODULES_LIST: True ADDITIONAL_ODOO_RC: "syslog = True" IR_CONFIG_PARAMETER: "web.base.url = https://odoo.example.com" + db_user_FILE: /run/secrets/db_user + db_password_FILE: /run/secrets/db_password + secrets: + - db_user + - db_password ports: - "127.0.0.1:8069:8069" volumes: @@ -194,6 +199,11 @@ services: volumes: odoo-data: db-data: +secrets: + db_user: + file: ./secrets/db_user.txt + db_password: + file: ./secrets/db_password.txt ``` The environment variables are explained in detail further down. @@ -477,6 +487,10 @@ Compatibility with other images is mainly achieved by using the same environment The `/etc/odoo/odoo.conf` is templated during container start. To output the content run `docker exec odoo conf`. +### requirements.txt + +If you mount a `requirements.txt` to `/var/lib/odoo/requirements.txt` the `install-python-packages` script will run `uv pip install -r requirements.txt ` in the directory. + ### pyproject.toml When mounting your `pyproject.toml` to `/var/lib/odoo/pyproject.toml` the `sync-python-project` script will run `uv sync --active` in the directory. @@ -502,11 +516,12 @@ See [Odoo Build > Build and publish container image](https://odoo.build/#build-a The most important image paths are: - `/etc/odoo` Contains the `odoo.conf` and `odoo.conf.template` files. -- `/mnt/extra-addons` Nested module are loaded from this path by default. -- `/mnt/test-addons` Recommended mount path for modules to test. +- `/mnt/extra-addons` Nested module folders are loaded from this path by default. +- `/mnt/test-addons` Default mount path for modules to test. - `/opt/odoo/addons` Contains the Odoo community edition modules. -- `/opt/odoo-venv` This is where Python packages are installed. -- `/var/lib/odoo` Odoo data folder. +- `/opt/odoo/venv` This is where Odoo packages are installed. +- `/var/lib/odoo` Odoo data folder for persistence. +- `/var/lib/odoo/venv` Additional Python packages are installed here. - `/var/lib/odoo/enterprise` Odoo enterprise modules are downloaded to this folder. - `/var/lib/odoo/filestore` For every database name Odoo creates a filestore. - `/var/lib/odoo/git` The cloned module repos are stored here. diff --git a/images/odoo/bin/conf b/images/odoo/bin/config similarity index 100% rename from images/odoo/bin/conf rename to images/odoo/bin/config diff --git a/images/odoo/bin/install-python-packages b/images/odoo/bin/install-python-packages index ee0f8f75..faa56c09 100755 --- a/images/odoo/bin/install-python-packages +++ b/images/odoo/bin/install-python-packages @@ -1,19 +1,25 @@ #!/usr/bin/env bash set -e +log-entrypoint 'Check status of PyPi.' +http_pypi_ok=$(curl -s --head --request GET https://pypi.org/simple/ --connect-timeout 5 --max-time 10 | grep 'HTTP/2 200') + +if [[ -z "$http_pypi_ok" ]]; then + log-entrypoint 'PyPI is unreachable. Installing from local cache or private repos may still work.' +fi + if [[ -n "$PYTHON_INSTALL" ]]; then - - log-entrypoint 'Check status of PyPi.' - http_pypi_ok=$(curl -s --head --request GET https://pypi.org/simple/ | grep 'HTTP/2 200') - - if [[ -n "$http_pypi_ok" ]]; then - # Handle both newline and comma-separated formats - if [[ "$PYTHON_INSTALL" == *","* ]]; then - # Comma-separated format - uv pip install $(echo "$PYTHON_INSTALL" | tr ',' ' ') - else - # Newline-separated or space-separated format - uv pip install $PYTHON_INSTALL - fi + # Handle both newline and comma-separated formats + if [[ "$PYTHON_INSTALL" == *","* ]]; then + # Comma-separated format + uv pip install $(echo "$PYTHON_INSTALL" | tr ',' ' ') + else + # Newline-separated or space-separated format + uv pip install $PYTHON_INSTALL fi fi + +if [[ -f "/var/lib/odoo/requirements.txt" ]]; then + log-entrypoint 'Installing Python packages from requirements.txt...' + uv pip install -r /var/lib/odoo/requirements.txt +fi diff --git a/images/odoo/entrypoint.sh b/images/odoo/entrypoint.sh index ba9a0d8c..1fa10bfc 100755 --- a/images/odoo/entrypoint.sh +++ b/images/odoo/entrypoint.sh @@ -34,9 +34,14 @@ DB_ARGS=() check_config() { local param="$1" local value="$2" - if grep -q -E "^\s*\b${param}\b\s*=" "$ODOO_RC" ; then - value=$(grep -E "^\s*\b${param}\b\s*=" "$ODOO_RC" |cut -d " " -f3|sed 's/["\n\r]//g') - fi; + local file_var="${param}_FILE" + + if [ -n "${!file_var}" ] && [ -f "${!file_var}" ]; then + value=$(cat "${!file_var}" | tr -d '\n\r' | sed 's/["\n\r]//g') + elif grep -q -E "^\s*\b${param}\b\s*=" "$ODOO_RC" ; then + value=$(grep -E "^\s*\b${param}\b\s*=" "$ODOO_RC" | cut -d " " -f3 | sed 's/["\n\r]//g') + fi + DB_ARGS+=("--${param}") DB_ARGS+=("${value}") } diff --git a/task b/task index 53718e7a..f90cb416 100755 --- a/task +++ b/task @@ -159,7 +159,7 @@ help-table() { rows+=("source||Source the Python virtual env.") rows+=("start|[name][db]|Start service. Use list to show services.") rows+=("stop|[name]|Stop containers.") - rows+=("test-xmlrpc|[env]|Test json rpc connection.") + rows+=("test-xmlrpc|[env]|Test xml rpc connection.") rows+=("===PROJECT===| | ") rows+=("lint||Run precommit for this project.") rows+=("list-versions||List available Odoo versions.") @@ -982,9 +982,9 @@ test-image() { echo -e "\033[38;5;214mTEST\033[0m: Sync python project." cat > tmp/pyproject.toml << 'EOF' [project] -name = "test-project" +name = "odoo-build-project" version = "0.1.0" -description = "Test project for uv sync" +description = "Test project for uv sync." dependencies = [ "requests>=2.28.0", "click>=8.0.0", @@ -1544,6 +1544,17 @@ test-project() { ELAPSED=$((ELAPSED + 3)) done + echo -e "\033[38;5;214mTEST\033[0m: Setup requirements.txt file." + exec odoo bash -c "echo 'click>=8.0.0' > /var/lib/odoo/requirements.txt" + exec odoo install-python-packages + click_path=$(exec odoo bash -c "python3 -c 'import click; print(click.__file__)'") + if echo "$click_path" | grep -q "/var/lib/odoo/venv/"; then + log-success "click is installed in persisted venv." + else + log-error "click is NOT in /var/lib/odoo/venv/ — found at: $click_path" + exit 1 + fi + echo -e "\033[38;5;214mTEST\033[0m: Init repos.yml file." cat << EOF > tmp/repos.yml github.com/Mint-System/Odoo-Apps-Partner-Contact: