Upgrading a working Docker setup from Specify 7.11.4 to 7.12.5

Specify 7 Version:
v7.11.4
Git SHA:

47823090fb12ee3df46a8122af8393dde65abbbb (Öffnet sich in einer neuen Registerkarte)
Datum des Builds:

vor 3 Monaten
Specify 6 Version:
6.8.03
Datenbankversion:
6.8.03
Datenbankschema-Version:

2.10
Datenbank-Name:
specify
Datenbank Erstelldatum:

Freitag, 3. März 2023 um 05:41:43
Institution:
Naturhistorisches Museum Bern
Discipline:
Invertebrate
Collection:
All-Invertebrates
ISA-Nummer:
N/A

Description

I’m currently upgrading a working Docker setup from Specify 7.11.4 to 7.12.5, and I’m having a hard time getting the database configuration to behave as expected.

In my previous setup, overriding database credentials worked fine. With 7.12.5, the same approach no longer seems to work.

I want to configure database credentials via environment variables and override them in local_specify_settings.py. via docker compompose. The environment variables are definitely present inside the container.

What happens

  • The overrides are ignored

  • The application connects using the default user (MasterUser)

  • This caused authentication issues during startup/migration

  • No clear error or warning indicates that overrides are not applied

What I expected

I expected local_specify_settings.py to override the default settings, as it did before (or at least as commonly expected in Django setups).

What I noticed (might be wrong)

While debugging, it looks like in:

specifyweb/settings/specify_settings.py

local_specify_settings.py is imported, but later somewhere DATABASES is defined or reassigned again, something like:

try:
    from .local_specify_settings import *
except ImportError:
    pass

# later
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'MasterUser',
        ...
    }
}

So it seems possible that my overrides are being overwritten afterwards.

My Workaround

When i redefinine/override the entire DATABASES dictionary inside local_specify_settings.pyit works like expected and the migration runs fine until the end and the system is in a working state. My settings looks then something like this:

import os

# --- ENV Variablen ---
DATABASE_NAME = os.environ['DATABASE_NAME']
DATABASE_HOST = os.environ['DATABASE_HOST']
DATABASE_PORT = os.environ.get('DATABASE_PORT', '')

MASTER_NAME = os.environ['MASTER_NAME']
MASTER_PASSWORD = os.environ['MASTER_PASSWORD']

APP_USER_NAME = os.environ.get('APP_USER_NAME', MASTER_NAME)
APP_USER_PASSWORD = os.environ.get('APP_USER_PASSWORD', MASTER_PASSWORD)

# --- FILES / PATHS ---
DEPOSITORY_DIR = '/volumes/static-files/depository'

REPORT_RUNNER_HOST = os.getenv('REPORT_RUNNER_HOST', '')
REPORT_RUNNER_PORT = os.getenv('REPORT_RUNNER_PORT', '')

WEB_ATTACHMENT_URL = os.getenv('ASSET_SERVER_URL', None)
WEB_ATTACHMENT_KEY = os.getenv('ASSET_SERVER_KEY', None)
WEB_ATTACHMENT_COLLECTION = os.getenv('ASSET_SERVER_COLLECTION', None)

SEPARATE_WEB_ATTACHMENT_FOLDERS = os.getenv('SEPARATE_WEB_ATTACHMENT_FOLDERS', None)

CELERY_BROKER_URL = os.getenv('CELERY_BROKER_URL', None)
CELERY_RESULT_BACKEND = os.getenv('CELERY_RESULT_BACKEND', None)
CELERY_TASK_DEFAULT_QUEUE = os.getenv('CELERY_TASK_QUEUE', DATABASE_NAME)

ANONYMOUS_USER = os.getenv('ANONYMOUS_USER', None)

SPECIFY_CONFIG_DIR = os.environ.get('SPECIFY_CONFIG_DIR', '/opt/Specify/config')

# --- OAuth ---
OAUTH_LOGIN_PROVIDERS = {
    'SOMETING': {
     SOMETHING
    },
}

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# ============================================================
# Workaround FIX
# ============================================================

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': DATABASE_NAME,
        'HOST': DATABASE_HOST,
        'PORT': DATABASE_PORT,
        'USER': APP_USER_NAME,
        'PASSWORD': APP_USER_PASSWORD,
        'OPTIONS': {
            'charset': 'utf8mb4',
        },
    }
}

Question

Is this a change in expected behavior in newer versions, or could this be related to the settings load order? Any guidance on the recommended way to configure database credentials in 7.12.5 would be helpful. Or Did i just missed some crucial readme somewhere or am i holding it wrong?

Thanks
Daniel

Hi @dfernandez,

Thanks for reaching out!

To summarize:

  • Specify 7.12.0.5 builds the final database settings after it reads local_specify_settings.py.
  • Because of that, any DATABASES = { ... } you set in local_specify_settings.py is overwritten later.
  • The supported way is to set the individual variables (like MASTER_NAME, APP_USER_NAME, etc.), and then Specify builds the database config from those.

What you should do:

  1. Make sure your environment variables are set in docker-compose
    Set these values in your environment or docker-compose.yml file:

    • DATABASE_NAME
    • DATABASE_HOST
    • DATABASE_PORT (optional)
    • MASTER_NAME
    • MASTER_PASSWORD
    • MIGRATOR_NAME, MIGRATOR_PASSWORD (optional)
    • APP_USER_NAME, APP_USER_PASSWORD (optional)
  2. Make sure Specify is loading the right settings file
    Your container must have:

    • /opt/specify7/settings/local_specify_settings.py
      If the file is mounted anywhere else inside the container, it will be ignored.

Verify:

  • Exec into the running container and check:
    • The file exists: /opt/specify7/settings/local_specify_settings.py
    • The environment variables are present: DATABASE_NAME, MASTER_NAME, etc.

This is not a bug; it’s how the settings are assembled in 7.12.0+. The fix is to set the variables via environment, not to redefine DATABASES.