docker icon indicating copy to clipboard operation
docker copied to clipboard

Configurable DB_NAME

Open singatias opened this issue 11 months ago • 4 comments

Hello,

Why is the database name hardcoded? Even if you change it in the odoo.conf, the Docker container won't be compatible with a PostgreSQL database that doesn't have a database named 'postgres'. Multiple people have reported this issue and created PRs to address it, but none of them have been taken seriously. I'm currently creating a Helm chart for Odoo and have to jump through hoops to get it set up.

#459 #426

Obviously these PRs were neglected for so long but it would be nice if the Odoo team merge a solution once and for all to this issue.

https://github.com/odoo/docker/blob/6b739618081fc0ff46032b38f5c126bafcdfe3a4/18.0/wait-for-psql.py#L21

https://github.com/odoo/docker/blob/6b739618081fc0ff46032b38f5c126bafcdfe3a4/18.0/entrypoint.sh#L9-L30

Best Regards, Mathias Beaulieu-Duncan

singatias avatar Dec 30 '24 17:12 singatias

I do not think they were neglected as much as it is being intentionally left unmerged .

As per this comment:

I understand your reasoning, but in this pull request, the additional --db_name argument to wait-for-psql.py is never passed from entrypoint.sh. When I got that far in my own experimentation, I noticed that entrypoint.sh sends the same arguments to both wait-for-psql.py and odoo, which causes non-multi-tenant setups to run Odoo out of the postgres database by default... which is less than ideal.

I'm not too sure what the issue with passing the same arguments here is. There is already a step in check_config which handles our args. If we dont specify a database, we can drop it from the arguments passed into the exec and wait command, and then just rely on arg_parser's default to wait for the postgres database.

I created a folder in my project called docker, which has the following files:

entrypoint.sh

#!/bin/bash

set -e

if [ -v PASSWORD_FILE ]; then
    PASSWORD="$(< $PASSWORD_FILE)"
fi

# set the postgres database host, port, user and password according to the environment
# and pass them as arguments to the odoo process if not present in the config file
: ${HOST:=${DB_PORT_5432_TCP_ADDR:='db'}}
: ${PORT:=${DB_PORT_5432_TCP_PORT:=5432}}
: ${USER:=${DB_ENV_POSTGRES_USER:=${POSTGRES_USER:='odoo'}}}
: ${PASSWORD:=${DB_ENV_POSTGRES_PASSWORD:=${POSTGRES_PASSWORD:='odoo'}}}
: ${DATABASE:=${DB_ENV_POSTGRES_DATABASE:=${POSTGRES_DATABASE}}}

DB_ARGS=()
function check_config() {
    param="$1"
    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;

    if [[ "$param" == "database" && -z "$value" ]]; then
        return
    fi;

    DB_ARGS+=("--${param}")
    DB_ARGS+=("${value}")
}

check_config "db_host" "$HOST"
check_config "db_port" "$PORT"
check_config "db_user" "$USER"
check_config "db_password" "$PASSWORD"
check_config "database" "$DATABASE"

case "$1" in
    -- | odoo)
        shift
        if [[ "$1" == "scaffold" ]] ; then
            exec odoo "$@"
        else
            wait-for-psql.py ${DB_ARGS[@]} --timeout=30
            exec odoo "$@" "${DB_ARGS[@]}"
        fi
        ;;
    -*)
        wait-for-psql.py ${DB_ARGS[@]} --timeout=30
        exec odoo "$@" "${DB_ARGS[@]}"
        ;;
    *)
        exec "$@"
esac

exit 1

wait-for-psql.py:


#!/usr/bin/env python3
import argparse
import psycopg2
import sys
import time


if __name__ == '__main__':
    arg_parser = argparse.ArgumentParser()
    arg_parser.add_argument('--db_host', required=True)
    arg_parser.add_argument('--db_port', required=True)
    arg_parser.add_argument('--db_user', required=True)
    arg_parser.add_argument('--db_password', required=True)
    arg_parser.add_argument('--timeout', type=int, default=5)
    arg_parser.add_argument('--database', default='postgres', required=False)

    args = arg_parser.parse_args()

    start_time = time.time()
    while (time.time() - start_time) < args.timeout:
        try:
            conn = psycopg2.connect(
                user=args.db_user,
                host=args.db_host,
                port=args.db_port,
                password=args.db_password,
                dbname=args.database
            )

            error = ''
            break
        except psycopg2.OperationalError as e:
            error = e
        else:
            conn.close()
        time.sleep(1)

    if error:
        print("Database connection failure: %s" % error, file=sys.stderr)
        sys.exit(1)

make the files executable:

chmod +x docker/entrypoint.sh && chmod +x docker/wait-for-psql.py

In my projects Dockerfile, I mount my version of these scripts:

FROM odoo:18.0


# Override the entrypoint and wait-for-psql.py file
COPY ./docker/entrypoint.sh /
COPY ./docker/wait-for-psql.py /usr/local/bin/wait-for-psql.py

Finally, I am able to control this in my docker-compose.yml file (or .env in my case) by setting

DATABASE=mydatabase

As far as I am able to tell this maintains the original functionality, just now with the ability to specify a database.

codebykyle avatar Feb 09 '25 14:02 codebykyle

Thanks for sharing your solution @codebykyle.

Have you tried it because I had similar solution changing these 2 files but I still couldn't get it to work, the Odoo executable threw an error on startup saying it doesn't recognize dbname parameter. I given up on Odoo since we found another suitable solution for our business needs.

singatias avatar Feb 09 '25 16:02 singatias

@singatias

Yes I've tried it, works fine.

Here are some examples:

Database is specified, but does not exist (wait-for-pysql.py fails) DATABASE=this_doesnt_exist Image

Database test exists, but does not have Odoo installed DATABASE=test: Image

Database param is specified but is empty (default behavior of Odoo) DATABASE=, or DATABASE is not in the env: Image

The parameter Odoo expects is --database not --dbname

See here

Database exists and Odoo is setup DATABASE=mydatabasename correctly selects that database.

codebykyle avatar Feb 09 '25 23:02 codebykyle

I created a pull request with the changes. This hopefully addresses the concerns of the user being locked into postgres if the database is not specified that was brought up in that earlier comment.

It would be really nice to have this functionality in the official Odoo docker container for multi-tenant setups.

Edit:

If anyone ends up here in the future, do not use the code in the comment above.

Check the PR, which now supports multiple database names. Hopefully this is merged and we can support this feature natively.

codebykyle avatar Feb 10 '25 00:02 codebykyle