A reproducible Docker environment for the protwis Django application — the backbone of GPCRdb. One docker compose up brings the full stack online: Django app, PostgreSQL with the RDKit cartridge, and Adminer.
Designed as the runtime companion to postgres_rdkit_docker, replacing the legacy conda-based local setup with a single uv-managed Python environment built on python:3.8-slim-bookworm.
| Service | URL / Port | Notes |
|---|---|---|
| Django app | http://localhost:8000 | source bind-mounted from the host; runserver auto-reloads on edit |
| PostgreSQL | localhost:5432 |
user protwis, password protwis, db protwis; RDKit cartridge enabled |
| Adminer | http://localhost:8888 | web SQL client; server name is db |
All three host-side ports are configurable via .env.
- Code-free image. The protwis source and the GPCRdb data tree are bind-mounted at runtime, never baked into the image. Upgrading Python or Django becomes a pure image rebuild — code remains untouched.
- No conda, no host-side Python. Dependencies are pure-pip via
uv; the resulting image is significantly smaller than the legacy conda baseline anduv sync --frozenresolves in seconds. - No invasive changes to protwis. Two additive
settings_*_docker.pyfiles register themselves underprotwis.settings_localviasys.modules; existing settings files are not modified. - Single source of truth for shared config. Site constants (
SITE_NAME,REFERENCE_POSITIONS,DOCUMENTATION_URL, …) live in the upstream local-settings file; the docker variants inherit them, so future edits propagate automatically. - Multi-stage build. Build tools (
build-essential,*-devheaders) live in the builder stage only; the final image ships only runtime shared libraries. - Reproducible across hosts. Same image, same dependency versions, same PostgreSQL extensions on every developer's machine. CI builds and smoke-tests every push.
- Docker Desktop running
- ~30 GB free disk space (for the postgres volume after the dump load)
git,curl
Tested on macOS (Apple Silicon and Intel) and Linux. On Windows, run inside WSL2.
-
Clone the three repositories side by side
mkdir -p ~/GitHub && cd ~/GitHub git clone -b dev_build https://github.com/protwis/protwis git clone https://github.com/protwis/gpcrdb_data git clone https://github.com/iskoldt-x/protwis_django_docker
The
dev_buildbranch is required — it carries the additivesettings_*_docker.pyfiles thatDJANGO_SETTINGS_MODULEresolves to. -
Copy the example env file (no edits required for the happy path)
cd protwis_django_docker cp .env.example .env -
Bring up the stack
docker compose up -d
The first start pulls the published images; subsequent starts take seconds.
-
Load the GPCRdb dump and apply migrations (~30–60 min)
curl -L https://files.gpcrdb.org/protwis_sp.sql.gz -o ~/protwis.sql.gz gunzip -c ~/protwis.sql.gz | docker exec -i gpcrdb-db psql -U protwis -d protwis -q -1 docker compose exec app python manage.py migrate
The
migratestep is required: the published dump may lag upstream code, so a small set of Django migrations brings the schema forward. See docs/onboarding.md §5 for the rationale.
.
├── Dockerfile # multi-stage, uv-driven, Python 3.8 on bookworm-slim
├── Dockerfile.full # adds MODELLER on top of the runtime image
├── docker-compose.yml # app + db + adminer; parameterised by .env
├── pyproject.toml # single source of truth for Python deps
├── pyproject.matrix.toml.tmpl # compatibility-matrix probe template (not deployable)
├── uv.lock # generated; committed for reproducibility
├── .env.example # main-stack env template — copy to .env
├── .env.alt # alt-stack env template — for side-by-side runs
├── scripts/ # compatibility-matrix pipeline (expand/run/merge/render)
├── docs/
│ ├── onboarding.md # long-form tutorial — start here as a new contributor
│ └── compatibility-matrix.md # generated; live (Python × Django × RDKit) results
├── LICENSE
├── README.md
└── .github/workflows/
├── ci.yml # build + smoke on every push/PR
├── docker-publish.yml # multi-arch runtime publish to ghcr.io on v* tags
├── docker-publish-full.yml # MODELLER-image publish (manual)
└── compatibility-matrix.yml # probe dependency combinations (manual)
The protwis source is bind-mounted into the app container, so host edits are live and Django's runserver auto-reloads. Common commands:
# Tail app logs (filter out deprecation noise)
docker compose logs -f app | grep -v "FutureWarning\|Deprecation"
# Drop into the app container
docker compose exec app bash
# Run any Django management command (see onboarding §8 for the pattern)
docker compose exec app python manage.py <command>
# Open a psql shell against the DB
docker exec -it gpcrdb-db psql -U protwis -d protwis
# Rebuild the app image after editing Dockerfile or pyproject.toml
docker compose build app
docker compose up -d app
# Stop the stack
docker compose down
# Reset the database (DESTRUCTIVE — drops the 26 GB postgres volume)
docker compose down -vFor long-running management commands, run detached and watch logs separately:
docker compose exec -T -d app python manage.py build_<something>
docker compose logs -f appA second isolated stack (separate ports, separate volume, separate network) coexists with the main one via the bundled .env.alt template:
docker compose --env-file .env.alt up -d # main on :8000, alt on :8001Useful for code-vs-code, dump-vs-dump, or before-vs-after comparisons.
| Workflow | Trigger | What it does |
|---|---|---|
ci.yml |
every push and PR to main |
builds the image and runs smoke tests (critical imports, Django boot, manage.py check) |
docker-publish.yml |
tags matching v* |
builds multi-arch (amd64 + arm64) and pushes to ghcr.io/iskoldt-x/protwis_django_docker |
compatibility-matrix.yml |
manual (workflow_dispatch) |
probes 36 (Python × Django × RDKit) combinations; pushes a per-combo image tag for every cell that builds and writes the result to docs/compatibility-matrix.md. Used to plan upgrades |
The published image is anonymously pullable, so docker compose up works on a fresh machine with no docker login step.
The whole point of moving off conda is making upgrades testable in CI rather than untestable on a laptop:
- Edit
pyproject.toml(typically a single pin bump). - Regenerate the lock locally:
uv lock. Withoutuvon the host, run it via the same Python container:docker run --rm -v "$PWD":/work -w /work python:3.8-slim-bookworm bash -c \ "apt-get update -qq && apt-get install -y -qq git && pip install -q uv && uv lock"
- Push — GitHub Actions builds the image and runs the smoke suite. If green, merge; if red, the failure points at the exact breakage.
- New contributor? Start with docs/onboarding.md — the full hand-holding tutorial covering daily-use commands, management commands, troubleshooting, and dual-stack workflows.
- Upstream code: https://github.com/protwis/protwis
- GPCRdb data: https://github.com/protwis/gpcrdb_data