这是indexloc提供的服务,不要输入任何密码
Skip to content

External database schema for pgAdmin user settings is not created #9125

@deceptiveSimplicity

Description

@deceptiveSimplicity

Describe the bug

When launching a pgAdmin 9.7.0 Docker container configured to use an external PostgreSQL database for user settings (PGADMIN_CONFIG_CONFIG_DATABASE_URI), the startup process fails. The container exits shortly after creation.

The root cause appears to be an unsuccessful database schema migration. The application log shows a psycopg.errors.UndefinedTable error because the relation module_preference does not exist, which suggests that the initial schema was not created in the external database.

To Reproduce

  1. Create a docker-compose.yml file in an empty directory with the following content:

    x-healthcheck: &healthcheck
      interval: 10s
      timeout: 5s
      start_period: 90s
      start_interval: 1s
    
    services:
      postgres:
        image: postgres:16.8
        environment:
          POSTGRES_HOST_AUTH_METHOD: trust
        volumes:
          - postgres:/var/lib/postgresql/data
        configs:
          - source: postgres-init
            target: /docker-entrypoint-initdb.d/00-init.sql
        healthcheck:
          <<: *healthcheck
          test: 'pg_isready -U postgres'
    
      pgadmin:
        image: dpage/pgadmin4:9.7.0
        depends_on:
          postgres:
            condition: service_healthy
        configs:
          - source: pgadmin-servers
            target: /pgadmin4/servers.json
          - source: pgadmin-pgpass
            target: /pgadmin4/.pgpass
            mode: 600
            uid: '5050'
            gid: '0'
        environment:
          PGADMIN_DEFAULT_EMAIL: admin@pgadmin.org
          PGADMIN_DEFAULT_PASSWORD: admin
          PGADMIN_DISABLE_POSTFIX: 'True'
          PGADMIN_CONFIG_SERVER_MODE: 'False'
          PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False'
          PGADMIN_CONFIG_CONFIG_DATABASE_URI: "'postgresql+psycopg://postgres@postgres:5432/pgAdmin'"
        healthcheck:
          <<: *healthcheck
          test: ['CMD', 'wget', '-O', '-', 'http://localhost:80/misc/ping']
        ports:
          - 8080:80
    
    configs:
      postgres-init:
        content: |
          CREATE DATABASE "pgAdmin";
    
      pgadmin-pgpass:
        content: 'postgres:5432:*:postgres:'
    
      pgadmin-servers:
        content: |
          {
            "Servers": {
              "1": {
                "Name": "Postgres",
                "Group": "Servers",
                "Host": "postgres",
                "Port": 5432,
                "MaintenanceDB": "postgres",
                "Username": "postgres",
                "ConnectionParameters": {
                  "passfile": "/pgadmin4/.pgpass"
                }
              }
            }
          }
    
    volumes:
      postgres:
  2. Run docker compose up --wait in the same directory.

  3. Observe the pgAdmin container failing to stay running.

Expected behavior

The pgAdmin container should start successfully and become healthy. The docker compose output should indicate that all containers are running and healthy. This behavior is achieved by using the 9.6.0 image tag, which works as expected with the same configuration.

Example of successful startup with 9.6.0:

[+] Running 4/4
 ✔ Network my-project_default               Created    0.0s
 ✔ Volume "my-project_postgres"             Created    0.0s
 ✔ Container my-project-postgres-1          Healthy    2.6s
 ✔ Container my-project-pgadmin-1           Healthy   29.5s

Error message

The docker compose command exits prematurely, showing the pgAdmin container has exited.

[+] Running 3/4
 ✔ Network my-project_default               Created    0.0s
 ✔ Volume "my-project_postgres"             Created    0.0s
 ✔ Container my-project-postgres-1          Healthy    2.6s
 - Container my-project-pgadmin-1           Waiting   20.6s
container my-project-pgadmin-1 exited (3)

The container log shows a traceback culminating in psycopg.errors.UndefinedTable: relation "module_preference" does not exist.

email config is {'CHECK_EMAIL_DELIVERABILITY': False, 'ALLOW_SPECIAL_EMAIL_DOMAINS': [], 'GLOBALLY_DELIVERABLE': True}
/venv/lib/python3.12/site-packages/passlib/pwd.py:16: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
Traceback (most recent call last):
NOTE: Configuring authentication for DESKTOP mode.
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute
    cursor.execute(statement, parameters)
  File "/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
psycopg.errors.UndefinedTable: relation "module_preference" does not exist
LINE 2: FROM module_preference
             ^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/pgadmin4/run_pgadmin.py", line 4, in <module>
    from pgAdmin4 import app
  File "/pgadmin4/pgAdmin4.py", line 93, in <module>
    app = create_app()
          ^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/__init__.py", line 476, in create_app
    run_migration_for_others()
  File "/pgadmin4/pgadmin/__init__.py", line 458, in run_migration_for_others
    db_upgrade(app)
  File "/pgadmin4/pgadmin/setup/db_upgrade.py", line 25, in db_upgrade
    flask_migrate.upgrade(migration_folder)
  File "/venv/lib/python3.12/site-packages/flask_migrate/__init__.py", line 111, in wrapped
    f(*args, **kwargs)
  File "/venv/lib/python3.12/site-packages/flask_migrate/__init__.py", line 200, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/venv/lib/python3.12/site-packages/alembic/command.py", line 483, in upgrade
    script.run_env()
  File "/venv/lib/python3.12/site-packages/alembic/script/base.py", line 549, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/venv/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 116, in load_python_file
    module = load_module_py(module_id, path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 136, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/setup/../../migrations/env.py", line 95, in <module>
    run_migrations_online()
  File "/pgadmin4/pgadmin/setup/../../migrations/env.py", line 87, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
  File "/venv/lib/python3.12/site-packages/alembic/runtime/environment.py", line 946, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/venv/lib/python3.12/site-packages/alembic/runtime/migration.py", line 627, in run_migrations
    step.migration_fn(**kw)
  File "/pgadmin4/migrations/versions/e6ed5dac37c2_.py", line 42, in upgrade
    register_editor_preferences(migration_obj, migration_gettext=lambda x: x)
  File "/pgadmin4/pgadmin/browser/register_editor_preferences.py", line 32, in register_editor_preferences
    self.editor_preference = Preferences(
                             ^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/utils/preferences.py", line 317, in __init__
    module = ModulePrefTable.query.filter_by(name=name).first()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/query.py", line 2759, in first
    return self.limit(1)._iter().first()  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/query.py", line 2857, in _iter
    result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
                                                  ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2365, in execute
    return self._execute_internal(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2251, in _execute_internal
    result: Result[Any] = compile_state_cls.orm_execute_statement(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/context.py", line 306, in orm_execute_statement
    result = conn.execute(
             ^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1419, in execute
    return meth(
           ^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context
    return self._exec_single_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context
    self._handle_dbapi_exception(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute
    cursor.execute(statement, parameters)
  File "/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedTable) relation "module_preference" does not exist
LINE 2: FROM module_preference
             ^
[SQL: SELECT module_preference.id AS module_preference_id, module_preference.name AS module_preference_name
FROM module_preference
WHERE module_preference.name = %(name_1)s::VARCHAR
 LIMIT %(param_1)s::INTEGER]
[parameters: {'name_1': 'editor', 'param_1': 1}]
(Background on this error at: https://sqlalche.me/e/20/f405)
/venv/lib/python3.12/site-packages/passlib/pwd.py:16: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
----------
Loading servers with:
User: pgadmin4@pgadmin.org
SQLite pgAdmin config: /var/lib/pgadmin/pgadmin4.db
----------
NOTE: Configuring authentication for DESKTOP mode.
(psycopg.errors.UndefinedTable) relation "module_preference" does not exist
LINE 2: FROM module_preference
             ^
[SQL: SELECT module_preference.id AS module_preference_id,
module_preference.name AS module_preference_name
FROM module_preference
WHERE module_preference.name = %(name_1)s::VARCHAR
 LIMIT %(param_1)s::INTEGER]

(Background on this error at: https://sqlalche.me/e/20/f405)
/venv/lib/python3.12/site-packages/passlib/pwd.py:16: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
/venv/lib/python3.12/site-packages/passlib/pwd.py:16: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  import pkg_resources
[2025-09-02 05:26:13 +0000] [1] [INFO] Starting gunicorn 23.0.0
[2025-09-02 05:26:13 +0000] [1] [INFO] Listening at: http://[::]:80 (1)
[2025-09-02 05:26:13 +0000] [1] [INFO] Using worker: gthread
[2025-09-02 05:26:13 +0000] [123] [INFO] Booting worker with pid: 123
[2025-09-02 05:26:15 +0000] [123] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute
    cursor.execute(statement, parameters)
  File "/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
psycopg.errors.UndefinedTable: relation "module_preference" does not exist
LINE 2: FROM module_preference
             ^

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/venv/lib/python3.12/site-packages/gunicorn/arbiter.py", line 608, in spawn_worker
    worker.init_process()
  File "/venv/lib/python3.12/site-packages/gunicorn/workers/gthread.py", line 94, in init_process
    super().init_process()
  File "/venv/lib/python3.12/site-packages/gunicorn/workers/base.py", line 135, in init_process
    self.load_wsgi()
  File "/venv/lib/python3.12/site-packages/gunicorn/workers/base.py", line 147, in load_wsgi
    self.wsgi = self.app.wsgi()
                ^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/gunicorn/app/base.py", line 66, in wsgi
    self.callable = self.load()
                    ^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/gunicorn/app/wsgiapp.py", line 57, in load
    return self.load_wsgiapp()
           ^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/gunicorn/app/wsgiapp.py", line 47, in load_wsgiapp
    return util.import_app(self.app_uri)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/gunicorn/util.py", line 370, in import_app
    mod = importlib.import_module(module)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 999, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/pgadmin4/run_pgadmin.py", line 4, in <module>
    from pgAdmin4 import app
  File "/pgadmin4/pgAdmin4.py", line 93, in <module>
    app = create_app()
          ^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/__init__.py", line 476, in create_app
    run_migration_for_others()
  File "/pgadmin4/pgadmin/__init__.py", line 458, in run_migration_for_others
    db_upgrade(app)
  File "/pgadmin4/pgadmin/setup/db_upgrade.py", line 25, in db_upgrade
    flask_migrate.upgrade(migration_folder)
  File "/venv/lib/python3.12/site-packages/flask_migrate/__init__.py", line 111, in wrapped
    f(*args, **kwargs)
  File "/venv/lib/python3.12/site-packages/flask_migrate/__init__.py", line 200, in upgrade
    command.upgrade(config, revision, sql=sql, tag=tag)
  File "/venv/lib/python3.12/site-packages/alembic/command.py", line 483, in upgrade
    script.run_env()
  File "/venv/lib/python3.12/site-packages/alembic/script/base.py", line 549, in run_env
    util.load_python_file(self.dir, "env.py")
  File "/venv/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 116, in load_python_file
    module = load_module_py(module_id, path)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/alembic/util/pyfiles.py", line 136, in load_module_py
    spec.loader.exec_module(module)  # type: ignore
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/setup/../../migrations/env.py", line 95, in <module>
    run_migrations_online()
  File "/pgadmin4/pgadmin/setup/../../migrations/env.py", line 87, in run_migrations_online
    context.run_migrations()
  File "<string>", line 8, in run_migrations
NOTE: Configuring authentication for DESKTOP mode.
  File "/venv/lib/python3.12/site-packages/alembic/runtime/environment.py", line 946, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/venv/lib/python3.12/site-packages/alembic/runtime/migration.py", line 627, in run_migrations
    step.migration_fn(**kw)
  File "/pgadmin4/migrations/versions/e6ed5dac37c2_.py", line 42, in upgrade
    register_editor_preferences(migration_obj, migration_gettext=lambda x: x)
  File "/pgadmin4/pgadmin/browser/register_editor_preferences.py", line 32, in register_editor_preferences
    self.editor_preference = Preferences(
                             ^^^^^^^^^^^^
  File "/pgadmin4/pgadmin/utils/preferences.py", line 317, in __init__
    module = ModulePrefTable.query.filter_by(name=name).first()
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/query.py", line 2759, in first
    return self.limit(1)._iter().first()  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/query.py", line 2857, in _iter
    result: Union[ScalarResult[_T], Result[_T]] = self.session.execute(
                                                  ^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2365, in execute
    return self._execute_internal(
           ^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2251, in _execute_internal
    result: Result[Any] = compile_state_cls.orm_execute_statement(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/orm/context.py", line 306, in orm_execute_statement
    result = conn.execute(
             ^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1419, in execute
    return meth(
           ^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 526, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1641, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context
    return self._exec_single_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context
    self._handle_dbapi_exception(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 951, in do_execute
    cursor.execute(statement, parameters)
  File "/venv/lib/python3.12/site-packages/psycopg/cursor.py", line 97, in execute
    raise ex.with_traceback(None)
sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedTable) relation "module_preference" does not exist
LINE 2: FROM module_preference
             ^
[SQL: SELECT module_preference.id AS module_preference_id, module_preference.name AS module_preference_name
FROM module_preference
WHERE module_preference.name = %(name_1)s::VARCHAR
 LIMIT %(param_1)s::INTEGER]
[parameters: {'name_1': 'editor', 'param_1': 1}]
(Background on this error at: https://sqlalche.me/e/20/f405)
[2025-09-02 05:26:15 +0000] [123] [INFO] Worker exiting (pid: 123)
[2025-09-02 05:26:15 +0000] [1] [ERROR] Worker (pid:123) exited with code 3
[2025-09-02 05:26:15 +0000] [1] [ERROR] Shutting down: Master
[2025-09-02 05:26:15 +0000] [1] [ERROR] Reason: Worker failed to boot.

Desktop

  • OS: Windows 11 (24H2, Build 26100.4946)
  • Docker: Docker Desktop 4.44.3
  • pgAdmin Version: 9.7.0
  • Mode: Desktop
  • Package Type: Container (from dpage/pgadmin4:9.7.0)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions