From 6d8e1d0830d76457a88c7aca75368bb37b3fc0de Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 25 Jun 2026 09:32:35 +0200 Subject: [PATCH] refactor(infra): bake config via dockerfile_inline, drop Dockerfile files (refs #30) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the three standalone Dockerfiles (openzaak, opennotificaties, keycloak) with `build.dockerfile_inline` recipes in the compose files, so the config bake has no separate Dockerfile artifacts to maintain. Behaviour is identical: each derived image still COPYies its config in. - oz-init / keycloak / flowable-init: 2-line inline Dockerfiles. - Open Notificaties needs no bake at all now — nrc-init runs migrations only, so all NRC services use the plain base image (removes a whole derived image). Why dockerfile_inline and not `docker cp` into named volumes: docker cp avoids images entirely but needs `docker compose create`, which podman-compose (the local dev runtime) does not implement — it would break `make openzaak-up` etc. locally. dockerfile_inline works on both podman-compose and the CI runner (verified both: oz-init + keycloak inline builds locally; flowable-init inline has been green on CI since run 27). Docs updated: gitea-actions-gotchas.md and openzaak.md. Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/runbooks/gitea-actions-gotchas.md | 24 +++++++++++------- docs/runbooks/openzaak.md | 6 ++--- infra/docker-compose.yml | 30 ++++++++++++++--------- infra/keycloak/Dockerfile | 7 ------ infra/keycloak/docker-compose.yml | 6 ++++- infra/opennotificaties/Dockerfile | 7 ------ infra/opennotificaties/docker-compose.yml | 12 +++------ infra/openzaak/Dockerfile | 12 --------- infra/openzaak/docker-compose.yml | 8 +++--- 9 files changed, 50 insertions(+), 62 deletions(-) delete mode 100644 infra/keycloak/Dockerfile delete mode 100644 infra/opennotificaties/Dockerfile delete mode 100644 infra/openzaak/Dockerfile diff --git a/docs/runbooks/gitea-actions-gotchas.md b/docs/runbooks/gitea-actions-gotchas.md index 280c682..7d8bd31 100644 --- a/docs/runbooks/gitea-actions-gotchas.md +++ b/docs/runbooks/gitea-actions-gotchas.md @@ -40,18 +40,24 @@ exposed it. **Fix: bake assets into derived images instead of bind-mounting them.** Anything a Compose service needs at runtime that lives in the repo is `COPY`-ed into a -small derived image, so it is present regardless of where the daemon runs: +small derived image, so it is present regardless of where the daemon runs. We use +**`build.dockerfile_inline`** — the 2-line recipe lives in the compose file, so +there are no standalone `Dockerfile` artifacts to maintain: -| Asset | Derived image | Dockerfile | +| Asset | Derived image | Built by | |---|---|---| -| OpenZaak `setup_configuration/data.yaml` | `register-referentie/openzaak:dev` | `infra/openzaak/Dockerfile` | -| Open Notificaties `setup_configuration/data.yaml` | `register-referentie/opennotificaties:dev` | `infra/opennotificaties/Dockerfile` | -| Keycloak realm exports | `register-referentie/keycloak:dev` | `infra/keycloak/Dockerfile` | -| `workflows/registratie.bpmn` | `register-referentie/flowable-init:dev` | `build.dockerfile_inline` in the compose files | +| OpenZaak `setup_configuration/data.yaml` | `register-referentie/openzaak:dev` | `oz-init` `dockerfile_inline` | +| Keycloak realm exports | `register-referentie/keycloak:dev` | `keycloak` `dockerfile_inline` | +| `workflows/registratie.bpmn` | `register-referentie/flowable-init:dev` | `flowable-init` `dockerfile_inline` | -The base image tag stays a build `arg` (`OPENZAAK_TAG`, `OPENNOTIFICATIES_TAG`) -so version pinning is unchanged. The three `*-init`/web/celery services that share -a base now share one built image tag, so the bake happens once per `up --build`. +The base image tag is interpolated by Compose (`${OPENZAAK_TAG}`) so pinning is +unchanged. OpenZaak's `openzaak`/`oz-celery` reuse the one image `oz-init` builds. +Open Notificaties needs **no** bake — `nrc-init` runs migrations only, so all NRC +services use the plain base image. + +`dockerfile_inline` works on both the CI runner (docker compose) and local +**podman-compose**, unlike `docker cp`-into-volumes (which needs `docker compose +create`, a subcommand podman-compose lacks). **Why not the alternatives.** diff --git a/docs/runbooks/openzaak.md b/docs/runbooks/openzaak.md index dc8b7fb..7196d2a 100644 --- a/docs/runbooks/openzaak.md +++ b/docs/runbooks/openzaak.md @@ -74,6 +74,6 @@ The Makefile auto-points `DOCKER_HOST` at the Podman socket when it exists, so t - **Image tag.** Pinned to `openzaak/open-zaak:1.28.2` via `${OPENZAAK_TAG}` (bump deliberately, not via `:latest`). - **Config is baked, not mounted.** `setup_configuration/data.yaml` is `COPY`-ed into - a derived image (`infra/openzaak/Dockerfile`) rather than bind-mounted, so the - init container finds it on Gitea's containerized CI runner too. See - [gitea-actions-gotchas.md](gitea-actions-gotchas.md). + a derived image via `oz-init`'s inline Dockerfile (`build.dockerfile_inline` in + the compose) rather than bind-mounted, so the init container finds it on Gitea's + containerized CI runner too. See [gitea-actions-gotchas.md](gitea-actions-gotchas.md). diff --git a/infra/docker-compose.yml b/infra/docker-compose.yml index 9a3fbe5..b63f7be 100644 --- a/infra/docker-compose.yml +++ b/infra/docker-compose.yml @@ -47,11 +47,16 @@ services: networks: [cg] oz-init: + # Derived image: base OpenZaak + the setup_configuration YAML baked in. We use + # an inline Dockerfile (not a separate file, not a bind mount) because bind + # mounts don't reach sibling containers on the containerized CI runner. + # The ${OPENZAAK_TAG} below is interpolated by Compose. See + # docs/runbooks/gitea-actions-gotchas.md. build: context: ./openzaak - dockerfile: Dockerfile - args: - OPENZAAK_TAG: ${OPENZAAK_TAG:-1.28.2} + dockerfile_inline: | + FROM docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2} + COPY setup_configuration /app/setup_configuration image: register-referentie/openzaak:dev environment: &oz-env DJANGO_SETTINGS_MODULE: openzaak.conf.docker @@ -127,12 +132,9 @@ services: networks: [cg] nrc-init: - build: - context: ./opennotificaties - dockerfile: Dockerfile - args: - OPENNOTIFICATIES_TAG: ${OPENNOTIFICATIES_TAG:-1.16.1} - image: register-referentie/opennotificaties:dev + # Plain base image — nrc-init runs migrations only (see command below), so it + # needs no baked config. + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: &nrc-env DJANGO_SETTINGS_MODULE: nrc.conf.docker SECRET_KEY: ${NRC_SECRET_KEY:-dev-only-not-for-production} @@ -165,7 +167,7 @@ services: networks: [cg] nrc-web: - image: register-referentie/opennotificaties:dev + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: *nrc-env healthcheck: test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.head('http://localhost:8000/admin/').status_code in (200,302) else 1)"] @@ -181,7 +183,7 @@ services: networks: [cg] nrc-celery: - image: register-referentie/opennotificaties:dev + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: *nrc-env command: /celery_worker.sh depends_on: @@ -191,9 +193,13 @@ services: # ── Keycloak (S-02) ────────────────────────────────────────────────────── keycloak: + # Derived image: base Keycloak + the realm exports baked into the import dir + # (inline Dockerfile, no bind mount — see docs/runbooks/gitea-actions-gotchas.md). build: context: ./keycloak - dockerfile: Dockerfile + dockerfile_inline: | + FROM quay.io/keycloak/keycloak:26.1 + COPY realms /opt/keycloak/data/import image: register-referentie/keycloak:dev command: ["start-dev", "--import-realm"] environment: diff --git a/infra/keycloak/Dockerfile b/infra/keycloak/Dockerfile deleted file mode 100644 index baec0c5..0000000 --- a/infra/keycloak/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -# Derived Keycloak image with the four realm exports baked into the import dir. -# `start-dev --import-realm` reads /opt/keycloak/data/import at boot. Baking the -# realms in (rather than bind-mounting ./realms) keeps the import working on -# Gitea's containerized runner, where bind mounts do not reach sibling -# containers. See docs/runbooks/gitea-actions-gotchas.md. -FROM quay.io/keycloak/keycloak:26.1 -COPY realms /opt/keycloak/data/import diff --git a/infra/keycloak/docker-compose.yml b/infra/keycloak/docker-compose.yml index eaf9088..7d74e0c 100644 --- a/infra/keycloak/docker-compose.yml +++ b/infra/keycloak/docker-compose.yml @@ -9,9 +9,13 @@ # Admin console: http://localhost:8180/ (admin / admin — dev only) services: keycloak: + # Derived image: base Keycloak + realm exports baked into the import dir via an + # inline Dockerfile. See docs/runbooks/gitea-actions-gotchas.md. build: context: . - dockerfile: Dockerfile + dockerfile_inline: | + FROM quay.io/keycloak/keycloak:26.1 + COPY realms /opt/keycloak/data/import image: register-referentie/keycloak:dev command: ["start-dev", "--import-realm"] environment: diff --git a/infra/opennotificaties/Dockerfile b/infra/opennotificaties/Dockerfile deleted file mode 100644 index f35f2ff..0000000 --- a/infra/opennotificaties/Dockerfile +++ /dev/null @@ -1,7 +0,0 @@ -# Derived Open Notificaties image with the setup_configuration YAML baked in. -# Rationale is identical to infra/openzaak/Dockerfile: bind mounts do not reach -# sibling containers on Gitea's containerized runner, so nrc-init would not find -# data.yaml. See docs/runbooks/gitea-actions-gotchas.md. -ARG OPENNOTIFICATIES_TAG=1.16.1 -FROM docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG} -COPY setup_configuration /app/setup_configuration diff --git a/infra/opennotificaties/docker-compose.yml b/infra/opennotificaties/docker-compose.yml index d2b8986..d333413 100644 --- a/infra/opennotificaties/docker-compose.yml +++ b/infra/opennotificaties/docker-compose.yml @@ -33,12 +33,8 @@ services: networks: [cg] nrc-init: - build: - context: . - dockerfile: Dockerfile - args: - OPENNOTIFICATIES_TAG: ${OPENNOTIFICATIES_TAG:-1.16.1} - image: register-referentie/opennotificaties:dev + # Plain base image — nrc-init runs migrations only (see command below). + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: &nrc-env DJANGO_SETTINGS_MODULE: nrc.conf.docker SECRET_KEY: ${NRC_SECRET_KEY:-dev-only-not-for-production} @@ -69,7 +65,7 @@ services: networks: [cg] nrc-web: - image: register-referentie/opennotificaties:dev + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: *nrc-env healthcheck: test: ["CMD", "python", "-c", "import requests,sys; sys.exit(0 if requests.head('http://localhost:8000/admin/').status_code in (200,302) else 1)"] @@ -85,7 +81,7 @@ services: networks: [cg] nrc-celery: - image: register-referentie/opennotificaties:dev + image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1} environment: *nrc-env command: /celery_worker.sh depends_on: diff --git a/infra/openzaak/Dockerfile b/infra/openzaak/Dockerfile deleted file mode 100644 index f827a81..0000000 --- a/infra/openzaak/Dockerfile +++ /dev/null @@ -1,12 +0,0 @@ -# Derived OpenZaak image with the setup_configuration YAML baked in. -# -# Why bake instead of bind-mount: Gitea's containerized `ubuntu-latest` runner -# runs the job inside a container, so `docker compose` starts the stack as -# SIBLING containers via the host daemon. A bind mount of a workspace path is -# then resolved on the daemon host (where it does not exist), and Docker mounts -# an empty directory — oz-init would not find data.yaml and exits 1. Baking the -# file into the image makes it present regardless of runtime (local Podman or -# CI Docker-in-Docker). See docs/runbooks/gitea-actions-gotchas.md. -ARG OPENZAAK_TAG=1.28.2 -FROM docker.io/openzaak/open-zaak:${OPENZAAK_TAG} -COPY setup_configuration /app/setup_configuration diff --git a/infra/openzaak/docker-compose.yml b/infra/openzaak/docker-compose.yml index 4eee276..c3c5174 100644 --- a/infra/openzaak/docker-compose.yml +++ b/infra/openzaak/docker-compose.yml @@ -32,11 +32,13 @@ services: networks: [cg] oz-init: + # Derived image: base OpenZaak + setup_configuration baked in via an inline + # Dockerfile. See docs/runbooks/gitea-actions-gotchas.md for why not a mount. build: context: . - dockerfile: Dockerfile - args: - OPENZAAK_TAG: ${OPENZAAK_TAG:-1.28.2} + dockerfile_inline: | + FROM docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2} + COPY setup_configuration /app/setup_configuration image: register-referentie/openzaak:dev environment: &oz-env DJANGO_SETTINGS_MODULE: openzaak.conf.docker