Skip to content

dhis2-chap/docker-dhis2-core

Repository files navigation

docker-dhis2-core

A simple Docker Compose setup for DHIS2 Core 2.42.5 with a PostGIS-backed PostgreSQL database.

Optionally, it can also bring up a chap-core v2.0.0 server (optionally with chapkit models such as EWARS) wired to DHIS2 through a DHIS2 Route — see Running with chap-core.

Prerequisites

  • Docker installed
  • Docker Compose v2.20+ (the docker compose plugin; the chap overlay uses the include directive, which legacy docker-compose does not support)
  • make (optional, but the documented commands use it)

.env setup (optional)

Every value has a working default baked into the compose files, so the stack runs without a .env. Create one only to change credentials or published ports — copy the template and edit:

cp .env.example .env

Docker Compose automatically loads .env from the project directory.

Database credentials use clean, prefixed variables (the compose files map them onto the images' own DB_* / POSTGRES_* names for you):

Variables Default
DHIS2_DB_NAME / DHIS2_DB_USER / DHIS2_DB_PASSWORD dhis / dhis / dhis
CHAP_DB_NAME / CHAP_DB_USER / CHAP_DB_PASSWORD chap_core / chap / chap

Start services

From the repository root (runs in the foreground — Ctrl+C to stop):

make start            # DHIS2 only
# equivalent to: docker compose up   (add -d to detach)

This starts the DHIS2-only stack (compose.yml):

  • dhis2-web - DHIS2 application (published on 127.0.0.1:8080)
  • dhis2-db - PostGIS database (published on 127.0.0.1:15432 for psql)
  • dhis2-db-dump - one-shot: downloads and prepares the database dump, then exits
  • dhis2-db-prep - one-shot (after the dump loads, before DHIS2 boots): runs ANALYZE so the freshly restored DB has query-planner statistics (without it the first analytics run takes ~20 min instead of ~20s), and resets any job left RUNNING (e.g. from a Ctrl+C mid-analytics) back to SCHEDULED so it can't block analytics. Runs on every start
  • dhis2-analytics - one-shot: after DHIS2 is healthy, generates the analytics_* tables (needed by the Data Visualizer, Climate app, and CHAP), then exits
  • chap-route-init - one-shot: repoints the demo dump's chap route (which ships aimed at a remote CHAP server) at host.docker.internal:8000 — i.e. a chap-core you run from source on the host. Set CHAP_ROUTE_URL to override the target. (The chap overlay points it at the bundled chap service instead — see below.)

First startup takes a few minutes: the dump loads, DHIS2 migrates and boots, then analytics-trigger populates analytics before exiting. Then open DHIS2 at:

http://127.0.0.1:8080

Default credentials: admin / district.

To also run chap-core alongside DHIS2, see Running with chap-core.

Ports & databases

Published on the host (env-overridable); EWARS and redis stay internal:

Var Service Bind Default
DHIS2_PORT DHIS2 web 127.0.0.1 8080 UI / API
CHAP_PORT chap-core 127.0.0.1 8000 API + /docs (no auth)
DHIS2_DB_PORT DHIS2 PostGIS 127.0.0.1 15432 browse with psql
CHAP_DB_PORT chap Postgres 127.0.0.1 15433 browse with psql

DHIS2_PORT and CHAP_PORT are the two you'll most likely change if 8080 / 8000 clash with other services already running on this machine:

DHIS2_PORT=8081 CHAP_PORT=8001 make start-chap

chap-core has no authentication, so CHAP_PORT binds 127.0.0.1 (loopback only, like the DBs). Remove the mapping to keep chap fully internal — DHIS2 still reaches it over the Compose network via the chap route either way.

Connect a SQL client to the data after make start-chap:

Host Port Database User Password
DHIS2 127.0.0.1 15432 dhis dhis dhis
chap 127.0.0.1 15433 chap_core chap chap
psql -h 127.0.0.1 -p 15432 -U dhis dhis      # DHIS2 data
psql -h 127.0.0.1 -p 15433 -U chap chap_core # chap data

The DB ports default to the 15xxx range to avoid clashing with a local postgres on 5432. Running several stacks? Give each its own .env with distinct ports.

Stop and reset

The start targets run in the foreground, so Ctrl+C stops the stack (containers remain and resume on the next make start).

For a full reset — remove containers, networks, and volumes (forces a fresh dump load and analytics run next time):

make clean
# equivalent to: docker compose -f compose.chapkit.yml down -v

Running with chap-core

make start-chap runs compose.chapkit.yml, the umbrella overlay for the whole chap stack. It includes, in layers:

  • compose.chap.ymlincludes the DHIS2 stack above and adds a chap-core v2.0.0 server, its worker / broker / database, and a one-shot that creates the DHIS2 Route connecting the two.
  • compose.ewars.yml — the EWARS chapkit model. Each chapkit model lives in its own per-model overlay (mirroring chap-core's own layout); add a model by copying this file and listing it in compose.chapkit.yml.

Bring up everything (DHIS2 + chap-core + chapkit models), foreground (Ctrl+C to stop):

make start-chap
# equivalent to: docker compose -f compose.chapkit.yml up   (add -d to detach)

This adds, on top of the DHIS2 services:

  • chap - chap-core REST API (internal; reached by DHIS2 at http://chap:8000)
  • chap-worker - Celery worker that runs the models (INLA/R baked in)
  • chap-redis - broker (internal)
  • chap-postgres - chap database (published on 127.0.0.1:15433 for psql)
  • chap-ewars - EWARS chapkit model; self-registers with chap on startup (internal)
  • chap-route-init - one-shot that wires up the DHIS2 → chap route, then exits

To run chap-core without the chapkit models, use the base overlay directly: docker compose -f compose.chap.yml up. To run a single model, stack its overlay on the base, e.g. docker compose -f compose.chap.yml -f compose.ewars.yml up.

How DHIS2 talks to chap

All access to chap-core goes through DHIS2, via a DHIS2 Route (a built-in reverse proxy) with code chap pointing at http://chap:8000/**. chap-core itself has no authentication, so it is never published to the host — DHIS2 is the only entry point, and it enforces auth.

chap-route-init sets this up automatically once DHIS2 is healthy (it runs in both stacks). It is self-correcting: the climate demo dumps ship a chap route aimed at an external CHAP server, so the one-shot repoints it rather than leaving the stale target in place. The target depends on the stack:

  • make start (DHIS2 only) → http://host.docker.internal:8000/** (a chap-core you run from source on the host; override with CHAP_ROUTE_URL).
  • make start-chap (overlay) → http://chap:8000/** (the bundled chap service).

Verify the route proxies through:

curl -u admin:district http://127.0.0.1:8080/api/routes/chap/run/health
# -> {"status":"success","message":"healthy"}

The manual equivalent (e.g. if you recreate it by hand) is a POST/PUT to /api/routes with {"name":"chap","code":"chap","url":"http://chap:8000/**"}.

chap API & Swagger UI

chap-core is published on the host at CHAP_PORT (default 8000), so its Swagger UI is at http://localhost:8000/docs and the API at http://localhost:8000/.... (No auth; bound to 127.0.0.1.)

To instead serve the docs through the DHIS2 route at http://localhost:8080/api/routes/chap/run/docs, uncomment the CHAP_ROOT_PATH line on the chap service in compose.chap.yml — that sets FastAPI's root_path so the proxied docs fetch the OpenAPI spec through the route instead of the DHIS2 origin. (The route itself works regardless; this only affects the proxied /docs page.)

Using chap from the DHIS2 UI

Install the Modelling App from the App Hub (App Management → App Hub). It uses the chap route above and the analytics_* tables populated by analytics-trigger. Installing apps is outside the scope of this compose setup.

Inspecting the data

Both databases are published on 127.0.0.1 so you can browse the data with psql — see Ports & databases for the connection details.

Notes

  • The chap-core and chap-worker images are pinned to the v2.0.0 tag (note the leading v). The EWARS chapkit model (compose.ewars.yml) tracks :latest (pulled on every up) so it doesn't go stale.
  • To stop and remove the chap-core volumes as well: docker compose -f compose.chapkit.yml down -v.

Notes

  • Published host ports — DHIS2 web, chap-core, and both databases — bind 127.0.0.1 and are env-overridable (see Ports & databases). EWARS and redis are internal to the Compose network.
  • The db-dump service downloads and patches the dump file into the named volume only once; deleting the volume forces it to re-download.
  • analytics-trigger runs the analytics export on first boot; it re-runs on every up (cheap if already current). DHIS2 needs a few GB of RAM for the populate phase — if the container gets OOM-killed mid-run, raise Docker's memory limit.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors