fix(infra): bake config into images so compose-smoke passes on CI (refs #30)
Some checks failed
CI / lint (pull_request) Successful in 50s
CI / build (pull_request) Successful in 40s
CI / unit (pull_request) Successful in 45s
CI / compose-smoke (pull_request) Failing after 3m31s

Root cause of the compose-smoke failure (found in the runner logs):

  oz-init-1 | CommandError: Yaml file
              `/app/setup_configuration/data.yaml` does not exist.

The ubuntu-latest runner runs the job inside a container, so
`docker compose up` starts the stack as SIBLING containers via the host
daemon. A relative bind mount (./openzaak/setup_configuration) resolves to
a path inside the job container that the daemon can't see, so Docker mounts
an empty dir and the init container can't find data.yaml. The same trap hit
nrc-init (data.yaml), flowable-init (the BPMN) and keycloak (realm import).

Fix: bake the assets into small derived images instead of bind-mounting:
  - infra/openzaak/Dockerfile        -> register-referentie/openzaak:dev
  - infra/opennotificaties/Dockerfile-> register-referentie/opennotificaties:dev
  - infra/keycloak/Dockerfile        -> register-referentie/keycloak:dev
  - flowable-init: build.dockerfile_inline bakes workflows/registratie.bpmn

Base versions stay build args (OPENZAAK_TAG / OPENNOTIFICATIES_TAG), so the
pinning is unchanged. Applied to both the consolidated compose and the
per-service composes, so local Podman and CI use one mechanism — no bind
mounts, no SELinux `:z`, no world-readable requirement.

Verified locally: `podman build` of the OpenZaak and BPMN images produces
the file at the expected in-container path.

Docs: docs/runbooks/gitea-actions-gotchas.md explains the DinD bind-mount
trap and the bake fix; openzaak.md and ci.md point at it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-24 13:06:56 +02:00
parent 88de47d1bb
commit 9ff7937055
11 changed files with 185 additions and 37 deletions

View File

@@ -47,7 +47,12 @@ services:
networks: [cg]
oz-init:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
build:
context: ./openzaak
dockerfile: Dockerfile
args:
OPENZAAK_TAG: ${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: &oz-env
DJANGO_SETTINGS_MODULE: openzaak.conf.docker
SECRET_KEY: ${OZ_SECRET_KEY:-dev-only-not-for-production}
@@ -68,8 +73,6 @@ services:
OPENZAAK_SUPERUSER_EMAIL: admin@localhost
RUN_SETUP_CONFIG: "true"
command: /setup_configuration.sh
volumes:
- ./openzaak/setup_configuration:/app/setup_configuration:ro
depends_on:
oz-db:
condition: service_healthy
@@ -78,7 +81,7 @@ services:
networks: [cg]
openzaak:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: *oz-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)"]
@@ -94,7 +97,7 @@ services:
networks: [cg]
oz-celery:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: *oz-env
command: /celery_worker.sh
depends_on:
@@ -124,7 +127,12 @@ services:
networks: [cg]
nrc-init:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
build:
context: ./opennotificaties
dockerfile: Dockerfile
args:
OPENNOTIFICATIES_TAG: ${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
environment: &nrc-env
DJANGO_SETTINGS_MODULE: nrc.conf.docker
SECRET_KEY: ${NRC_SECRET_KEY:-dev-only-not-for-production}
@@ -144,8 +152,6 @@ services:
OPENNOTIFICATIES_SUPERUSER_EMAIL: admin@localhost
RUN_SETUP_CONFIG: "true"
command: /setup_configuration.sh
volumes:
- ./opennotificaties/setup_configuration:/app/setup_configuration:ro
depends_on:
nrc-db:
condition: service_healthy
@@ -156,7 +162,7 @@ services:
networks: [cg]
nrc-web:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
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)"]
@@ -172,7 +178,7 @@ services:
networks: [cg]
nrc-celery:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
environment: *nrc-env
command: /celery_worker.sh
depends_on:
@@ -182,7 +188,10 @@ services:
# ── Keycloak (S-02) ──────────────────────────────────────────────────────
keycloak:
image: quay.io/keycloak/keycloak:26.1
build:
context: ./keycloak
dockerfile: Dockerfile
image: register-referentie/keycloak:dev
command: ["start-dev", "--import-realm"]
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
@@ -193,8 +202,6 @@ services:
KC_HTTP_ENABLED: "true"
ports:
- "8180:8080"
volumes:
- ./keycloak/realms:/opt/keycloak/data/import:ro
networks: [cg]
# ── Flowable (S-03) ──────────────────────────────────────────────────────
@@ -228,10 +235,16 @@ services:
networks: [cg]
flowable-init:
image: docker.io/curlimages/curl:latest
# The BPMN is baked into a tiny curl image (build context = repo-root
# workflows/) instead of bind-mounted, so the deploy works on Gitea's
# containerized runner too. See docs/runbooks/gitea-actions-gotchas.md.
build:
context: ../workflows
dockerfile_inline: |
FROM docker.io/curlimages/curl:latest
COPY registratie.bpmn /work/registratie.bpmn
image: register-referentie/flowable-init:dev
restart: "no"
volumes:
- ../workflows/registratie.bpmn:/work/registratie.bpmn:ro
command:
- sh
- -c

View File

@@ -38,10 +38,16 @@ services:
# Deploys workflows/registratie.bpmn via the REST API once flowable-rest is up.
# Idempotent: skips if a deployment named "registratie" already exists.
flowable-init:
image: docker.io/curlimages/curl:latest
# The BPMN is baked into a tiny curl image (build context = repo-root
# workflows/) instead of bind-mounted, so the deploy works on Gitea's
# containerized runner too. See docs/runbooks/gitea-actions-gotchas.md.
build:
context: ../../workflows
dockerfile_inline: |
FROM docker.io/curlimages/curl:latest
COPY registratie.bpmn /work/registratie.bpmn
image: register-referentie/flowable-init:dev
restart: "no"
volumes:
- ../../workflows/registratie.bpmn:/work/registratie.bpmn:ro,z
command:
- sh
- -c

View File

@@ -0,0 +1,7 @@
# 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

View File

@@ -9,7 +9,10 @@
# Admin console: http://localhost:8180/ (admin / admin — dev only)
services:
keycloak:
image: quay.io/keycloak/keycloak:26.1
build:
context: .
dockerfile: Dockerfile
image: register-referentie/keycloak:dev
command: ["start-dev", "--import-realm"]
environment:
KC_BOOTSTRAP_ADMIN_USERNAME: admin
@@ -21,8 +24,6 @@ services:
KC_HTTP_ENABLED: "true"
ports:
- "8180:8080"
volumes:
- ./realms:/opt/keycloak/data/import:ro,z
networks: [cg]
networks:

View File

@@ -0,0 +1,7 @@
# 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

View File

@@ -19,10 +19,13 @@ services:
volumes:
- nrc-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U opennotificaties -d opennotificaties"]
# pg_isready only checks TCP; the second clause verifies PostGIS is installed
# so nrc-init migrations can safely start (avoids race on cold container start).
test: ["CMD-SHELL", "pg_isready -U opennotificaties -d opennotificaties && psql -U opennotificaties -d opennotificaties -c 'SELECT PostGIS_Version();' -q 2>/dev/null"]
interval: 5s
timeout: 3s
retries: 10
timeout: 5s
retries: 30
start_period: 15s
networks: [cg]
nrc-redis:
@@ -30,7 +33,12 @@ services:
networks: [cg]
nrc-init:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
build:
context: .
dockerfile: Dockerfile
args:
OPENNOTIFICATIES_TAG: ${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
environment: &nrc-env
DJANGO_SETTINGS_MODULE: nrc.conf.docker
SECRET_KEY: ${NRC_SECRET_KEY:-dev-only-not-for-production}
@@ -50,8 +58,6 @@ services:
OPENNOTIFICATIES_SUPERUSER_EMAIL: admin@localhost
RUN_SETUP_CONFIG: "true"
command: /setup_configuration.sh
volumes:
- ./setup_configuration:/app/setup_configuration:ro,z
depends_on:
nrc-db:
condition: service_healthy
@@ -60,7 +66,7 @@ services:
networks: [cg]
nrc-web:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
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)"]
@@ -76,7 +82,7 @@ services:
networks: [cg]
nrc-celery:
image: docker.io/openzaak/open-notificaties:${OPENNOTIFICATIES_TAG:-1.16.1}
image: register-referentie/opennotificaties:dev
environment: *nrc-env
command: /celery_worker.sh
depends_on:

12
infra/openzaak/Dockerfile Normal file
View File

@@ -0,0 +1,12 @@
# 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

View File

@@ -32,7 +32,12 @@ services:
networks: [cg]
oz-init:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
build:
context: .
dockerfile: Dockerfile
args:
OPENZAAK_TAG: ${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: &oz-env
DJANGO_SETTINGS_MODULE: openzaak.conf.docker
SECRET_KEY: ${OZ_SECRET_KEY:-dev-only-not-for-production}
@@ -55,8 +60,6 @@ services:
OPENZAAK_SUPERUSER_EMAIL: admin@localhost
RUN_SETUP_CONFIG: "true"
command: /setup_configuration.sh
volumes:
- ./setup_configuration:/app/setup_configuration:ro
depends_on:
oz-db:
condition: service_healthy
@@ -65,7 +68,7 @@ services:
networks: [cg]
openzaak:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: *oz-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)"]
@@ -81,7 +84,7 @@ services:
networks: [cg]
oz-celery:
image: docker.io/openzaak/open-zaak:${OPENZAAK_TAG:-1.28.2}
image: register-referentie/openzaak:dev
environment: *oz-env
command: /celery_worker.sh
depends_on: