Skip to content

Commit eae3b72

Browse files
committed
feat: [#2638] add docker compose setup for Open Zaak, Objects APIs, HC BRP mock and OpenKlant
Closes: #2638
1 parent fe1bed2 commit eae3b72

29 files changed

Lines changed: 3955 additions & 235 deletions

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ local.py
3434
/env/
3535
/media/
3636
/private_media/
37+
/tempo-data/
3738
/static/
3839
/mail/
3940
/log/*.log*

bin/ensure_dev_network.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
#
3+
# Idempotently create the `open-inwoner-dev` Docker network used by the root
4+
# docker-compose.yml and every satellite compose file under docker/
5+
# (open-zaak, objects-apis, hc-brp-mock, openklant, keycloak, observability).
6+
#
7+
# All of those files attach to this network as `external: true` rather than
8+
# creating it themselves, so that combining several of them in one `docker
9+
# compose` invocation (or running them as separate `up` commands) never races
10+
# over which one "owns" it -- see docs/installation/docker-compose.rst.
11+
#
12+
# Run this once before bringing up any stack for the first time. Safe to
13+
# re-run; it's a no-op if the network already exists. `bin/stack.sh up` calls
14+
# this for you.
15+
16+
set -e
17+
18+
NETWORK_NAME="open-inwoner-dev"
19+
20+
if docker network inspect "$NETWORK_NAME" >/dev/null 2>&1; then
21+
echo "Network '$NETWORK_NAME' already exists."
22+
else
23+
echo "Creating network '$NETWORK_NAME'..."
24+
docker network create "$NETWORK_NAME"
25+
fi

bin/setup_configuration.sh

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,42 @@ SCRIPTPATH=$(dirname "$SCRIPT")
1212
${SCRIPTPATH}/wait_for_db.sh
1313

1414
src/manage.py migrate
15-
src/manage.py setup_configuration \
16-
--yaml-file /app/setup_configuration/data.yaml
15+
16+
# `setup_configuration` steps like OpenZaakConfigurationStep and
17+
# KlantenSysteemConfigurationStep converge fields back to whatever data.yaml
18+
# says on every run (see their docstrings), overwriting any changes made
19+
# through the admin in the meantime. That's fine for a first run against a
20+
# fresh database, but not for every subsequent `docker compose up`/restart of
21+
# an already-configured dev environment. Only run it once per database: a
22+
# marker in a persistent volume (mounted only into this container, see
23+
# docker-compose.yml) records that it already ran.
24+
MARKER_DIR=${SETUP_CONFIGURATION_STATE_DIR:-/var/lib/open-inwoner/setup-configuration}
25+
MARKER="${MARKER_DIR}/.completed"
26+
27+
if [ -f "$MARKER" ]; then
28+
echo "setup_configuration already completed previously (marker: $MARKER); skipping."
29+
echo "Remove that file, or the setup_configuration_state volume, to force a re-run."
30+
else
31+
src/manage.py setup_configuration \
32+
--yaml-file /app/setup_configuration/data.yaml
33+
34+
# CatalogusConfig/ZaakTypeConfig/ZaakType*TypeConfig are normally
35+
# populated by the `zgw_import_data` management command (also run daily
36+
# via Celery beat, see CELERY_BEAT_SCHEDULE in conf/base.py), which
37+
# discovers catalog data from the ZGW APIs live and upserts by
38+
# url/identificatie. We load a fixture instead of running that command
39+
# here, because it also pins fields the importer never touches --
40+
# notify_status_changes, document_upload_enabled, status_indicator, etc.
41+
# -- to specific values useful for visually testing case-visibility
42+
# rules. This fixture is a snapshot: it was produced by running
43+
# `zgw_import_data` for real against a stack seeded with
44+
# seed_openzaak_fixtures.py (see repository root), then hand-editing in
45+
# the OIP-only fields and `dumpdata`-ing the openzaak app's Config
46+
# models. Its URLs/UUIDs must match docker/open-zaak/fixtures/
47+
# open_zaak_fixtures.json's catalog rows -- if you regenerate one,
48+
# regenerate the other the same way.
49+
src/manage.py loaddata /app/setup_configuration/fixtures/openzaak_config.json
50+
51+
mkdir -p "$MARKER_DIR"
52+
touch "$MARKER"
53+
fi

bin/stack.sh

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/bin/bash
2+
#
3+
# Manage the full local Open Inwoner stack: the main app plus every
4+
# satellite service it talks to (Keycloak for OIDC, Open Zaak, the
5+
# Objects/Objecttypes APIs, the Haal Centraal BRP mock, Open Klant, and Open
6+
# Afval), plus the observability stack (Grafana/Loki/Prometheus/otel-collector).
7+
#
8+
# Usage:
9+
# bin/stack.sh up # bring everything up: network, then satellites
10+
# # (waited on until healthy), then the app
11+
# bin/stack.sh up --logs # ...then follow the main app's logs
12+
# bin/stack.sh down # stop and remove containers, keep volumes/data
13+
# bin/stack.sh down -v # ...and remove volumes too (wipes all data)
14+
# bin/stack.sh urls # print the service URLs shown at the end of `up`
15+
# bin/stack.sh logs [args] # forwarded to `docker compose logs`
16+
# bin/stack.sh <cmd> [args] # anything else forwarded to `docker compose`,
17+
# # e.g. `bin/stack.sh ps`, `bin/stack.sh exec web bash`
18+
#
19+
# Run from anywhere; this always operates from the repository root.
20+
#
21+
# web-init's setup_configuration run needs Keycloak (OIDC discovery) and the
22+
# ZGW/Open Klant services reachable, which is why `up` waits for those before
23+
# starting the app. See docs/installation/docker-compose.rst for the full
24+
# explanation and how to bring stacks up individually.
25+
26+
set -e
27+
28+
SCRIPT=$(readlink -f "$0")
29+
REPO_ROOT=$(dirname "$(dirname "$SCRIPT")")
30+
cd "$REPO_ROOT"
31+
32+
# docker-compose.dev.yml pulls in docker-compose.yml (the main app stack) and
33+
# docker/docker-compose.keycloak.yml (OIDC) via `include:`, which resolves
34+
# each file's relative paths against its own directory -- required for
35+
# Keycloak's realm fixture mount to resolve correctly. The remaining
36+
# satellite files use paths relative to the repository root instead, which
37+
# works fine alongside `include:` since they're passed as plain `-f` files.
38+
# See docker-compose.dev.yml's header comment for the full reasoning.
39+
COMPOSE=(
40+
docker compose
41+
-f docker-compose.dev.yml
42+
-f docker/docker-compose.open-zaak.yml
43+
-f docker/docker-compose.objects-apis.yml
44+
-f docker/docker-compose.hc-brp-mock.yml
45+
-f docker/docker-compose.openklant.yml
46+
-f docker/docker-compose.openafval.yml
47+
-f docker/docker-compose.observability.yml
48+
)
49+
50+
print_urls() {
51+
cat <<'EOF'
52+
Open Inwoner http://localhost:8000/ (behind nginx: http://localhost:9000/)
53+
Open Inwoner admin http://localhost:8000/admin/ (click "Login with OIDC", Keycloak admin / admin)
54+
Mailpit (sent emails) http://localhost:8025/
55+
Keycloak admin http://localhost:8080/ (admin / admin)
56+
Open Zaak admin http://localhost:8002/admin/ (admin / admin)
57+
Objecttypes API admin http://localhost:8003/admin/ (admin / admin)
58+
Objects API admin http://localhost:8004/admin/ (admin / admin)
59+
Open Klant admin http://localhost:8338/admin/ (admin / admin)
60+
Open Afval admin http://localhost:8339/admin/
61+
Haal Centraal BRP mock http://localhost:5010/
62+
Grafana (observability) http://localhost:3000/
63+
Prometheus http://localhost:9090/
64+
Loki http://localhost:3100/ready
65+
66+
DigiD login http://localhost:8000/digid-oidc/authenticate/
67+
eHerkenning login http://localhost:8000/eherkenning-oidc/authenticate/
68+
eIDAS login http://localhost:8000/eidas-oidc/authenticate/
69+
(any Keycloak test user works -- see docker/keycloak/README.md for the
70+
full list, including DigiD machtigen and eHerkenning bewindvoering/vestiging)
71+
EOF
72+
}
73+
74+
cmd=${1:-}
75+
[ $# -gt 0 ] && shift
76+
77+
case "$cmd" in
78+
up)
79+
echo "==> Ensuring the shared open-inwoner-dev network exists"
80+
bin/ensure_dev_network.sh
81+
82+
echo
83+
echo "==> Starting satellite services (Keycloak, Open Zaak, Objects APIs, Haal Centraal BRP mock, Open Klant, Open Afval)"
84+
echo " web-init needs all of these reachable, so they come up -- and are waited on -- first."
85+
"${COMPOSE[@]}" up -d --wait \
86+
keycloak \
87+
openzaak-web openzaak-celery \
88+
objecttypes-web objects-web objects-celery \
89+
personen-mock \
90+
openklant-seed \
91+
openafval-seed
92+
93+
echo
94+
echo "==> Starting the main app stack (web-init will now configure it against the services above)"
95+
# OTEL_SDK_DISABLED defaults to true in docker-compose.yml's shared
96+
# x-app-env (so plain `docker compose up` stays opt-in, per
97+
# docs/installation/docker-compose.rst) -- overridden here since this
98+
# script also brings up the observability stack itself, and running
99+
# Grafana/Loki/Prometheus with nothing feeding them defeats the point.
100+
OTEL_SDK_DISABLED=false "${COMPOSE[@]}" up -d
101+
102+
echo
103+
echo "==> Stack is up."
104+
echo
105+
print_urls
106+
echo
107+
echo "Bring it all down again with:"
108+
echo " bin/stack.sh down"
109+
110+
if [ "$1" = "--logs" ]; then
111+
"${COMPOSE[@]}" logs -f web web-init
112+
fi
113+
;;
114+
115+
urls)
116+
print_urls
117+
;;
118+
119+
down)
120+
echo "==> Stopping and removing containers"
121+
"${COMPOSE[@]}" down --remove-orphans "$@"
122+
echo
123+
echo "The shared open-inwoner-dev network is left in place (it's external to"
124+
echo "every compose file here). Remove it yourself if you need to, with:"
125+
echo " docker network rm open-inwoner-dev"
126+
;;
127+
128+
reset-config)
129+
# web-init is a one-shot container, not a running service, so its
130+
# marker (see bin/setup_configuration.sh) can't be removed with
131+
# `exec` -- use a throwaway container against the same volume instead.
132+
echo "==> Clearing the setup_configuration marker"
133+
"${COMPOSE[@]}" run --rm --entrypoint sh web-init -c \
134+
"rm -f /var/lib/open-inwoner/setup-configuration/.completed"
135+
136+
echo
137+
echo "==> Re-running web-init"
138+
"${COMPOSE[@]}" up -d web-init
139+
;;
140+
141+
""|-h|--help)
142+
cat <<'EOF'
143+
Usage: bin/stack.sh <command> [args]
144+
145+
Commands:
146+
up [--logs] Bring up the full stack: network, then satellites
147+
(waited on until healthy), then the app.
148+
down [args] Stop and remove containers. Forwarded to
149+
`docker compose down` (e.g. `bin/stack.sh down -v` to
150+
also remove volumes).
151+
reset-config Force setup_configuration to run again on next `up`
152+
(e.g. after editing docker/setup_configuration/data.yaml),
153+
instead of being skipped as already-completed.
154+
urls Print the service URLs shown at the end of `up`, without
155+
bringing anything up or down.
156+
<anything else> Forwarded to `docker compose` as-is, e.g.:
157+
bin/stack.sh ps
158+
bin/stack.sh logs -f openklant-web
159+
bin/stack.sh exec web bash
160+
EOF
161+
;;
162+
163+
*)
164+
"${COMPOSE[@]}" "$cmd" "$@"
165+
;;
166+
esac

docker-compose.dev.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
# - the root compose's ./docker/setup_configuration mount, and
99
# - the keycloak compose's ./keycloak/fixtures/realm.json mount
1010
# resolve correctly. A plain `-f a -f b` shares a single project directory and would
11-
# break one of the two (empty-dir bind mounts). Both services share the explicitly
12-
# named `openinwoner-dev` network, so the backend can reach Keycloak.
11+
# break one of the two (empty-dir bind mounts). Both services attach to the same
12+
# external `open-inwoner-dev` network, so the backend can reach Keycloak; run
13+
# `bin/ensure_dev_network.sh` once before using this file (see
14+
# docs/installation/docker-compose.rst).
1315
include:
1416
- docker-compose.yml
1517
- docker/docker-compose.keycloak.yml

0 commit comments

Comments
 (0)