Container build en preview deployment via ZAD#844
Conversation
- Multi-stage Containerfile: MkDocs build + nginx-unprivileged with security headers - Preview workflow: builds and deploys to ZAD on PRs and push to main - Production workflow: builds and deploys to ZAD on version tags - Remove Material Insiders dependency (now free in public repo) - Fix getBasePath() in modal.js to use MkDocs base element instead of hardcoded paths - Remove .claude/ from git, add to .gitignore
Voorkomt dat relatieve paden breken wanneer een directory-URL zonder trailing slash wordt opgevraagd (bijv. /kader → /kader/).
numpy>=2.4 vereist Python >=3.11; consistent met Containerfile.
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ment # Conflicts: # .github/workflows/preview.yaml # README.md
Info voor Algoritmeregister-teamRouting-eis voor de Algoritmekader-container (productie)Wat je krijgtEen container (poort 8080, unprivileged nginx) die de statisch gebouwde Algoritmekader-website serveert. De bestanden staan op de root van de webserver (/usr/share/nginx/html), dus bv. GET / → homepage, GET /voldoen-aan-wetten-en-regels/vereisten/ → die pagina. De eis: prefix /kader/ moet vóór de container worden gestript De site wordt gebouwd met SITE_URL=https://algoritmes.overheid.nl/kader/. Daardoor zet MkDocs en krijgen alle interne links, assets (CSS/JS) De ingress/reverse proxy vóór de container moet het /kader-prefix verwijderen voordat het request de container bereikt:
Doe je dat niet, dan laadt de homepage misschien wél, maar 404'en alle interne links en assets (de pagina komt kapot/zonder opmaak binnen). Voorbeeld (Kubernetes nginx-ingress)(Op een ander platform: gelijkwaardige "strip path prefix /kader"-regel.) Goed om te weten
Verificatie na deploy
BeslispuntKan/mag de ingress het prefix niet strippen? Dan moet de container in plaats daarvan op de root van het domein gehost worden en gebouwd worden met SITE_URL=https://algoritmes.overheid.nl/ (zónder /kader/). Dat wijzigt wel de publieke URL. Graag bevestigen welke van de twee het wordt. |
There was a problem hiding this comment.
Is dit mogelijk?
Claude: github.event.repository.name behoudt de hoofdletters van de repo ("Algoritmekader"), terwijl GHCR de package lowercase opslaat ("algoritmekader/preview", want metadata-action lowercased bij de push). Als de API hoofdlettergevoelig is, matcht deze query niet en blijven afgesloten PR-images in GHCR staan (cleanup faalt stil door de2>/dev/null + exit 0). Indien dit speelt: lowercasen met CONTAINER_NAME="${CONTAINER_NAME,,}".
MkDocs Material genereert geen <base> element, dus getBasePath() viel altijd terug op '' en de beslishulp 404'de op deployments met een pad-prefix (/kader, /Algoritmekader). Het prefix wordt nu build-time uit site_url afgeleid en als window.AK_BASE_PATH geinjecteerd, zodat het op elke deployment klopt.
De image werd per omgeving gebouwd (SITE_URL build-arg). Nu een omgevings- onafhankelijke image: gebouwd met een vaste placeholder-site_url, waarna nginx bij startup de echte origin + pad-prefix (uit $SITE_URL) injecteert via envsubst + sub_filter -- in canonical/sitemap, de 404-assets en window.AK_BASE_PATH. $SITE_URL afwezig => serveren op root. Werkt rootless en op een read-only root filesystem (output naar tmpfs). De env wordt in de ZAD-deployment-config gezet, niet build-time.
…tput halen Het clusterdomein werd hardcoded in de workflow samengesteld. De ZAD deploy- action geeft de URL zelf terug (steps.deploy.outputs.url) en plaatst de PR- comment; de handmatige constructie (en de ongebruikte name/url-outputs) zijn verwijderd. Alleen de image-tagprefix wordt nog afgeleid.
- docker/{setup-buildx@v4,login@v4,metadata@v6,build-push@v7}: lost de
Node.js 20-deprecation op (deze majors draaien op Node 24).
- RijksICTGilde/zad-actions deploy+cleanup van v2 naar v4: v4 leest de
deploy-URL uit de zad-cli JSON-output i.p.v. te raden, wat de
'Could not extract URL from API response'-warning verhelpt.
Runtime-stage nu FROM ghcr.io/rijksictgilde/nginx-base (gepind op tag+digest): dagelijks gepatcht, gesigned + SBOM, non-root, read-only-rootfs. We leveren een eigen nginx.conf + server-template + security-headers.conf erbovenop -- met de runtime SITE_URL-injectie behouden, en hun hardening overgenomen: GET/HEAD-only (405), dotfiles geblokkeerd, asset-caching, en extra headers (object-src 'none', base-uri/frame-ancestors 'self', COOP/CORP, X-Permitted-Cross-Domain-Policies) naast onze strikte CSP.
…kerignore Dependabot's docker-ecosystem detecteert alleen 'Dockerfile', niet 'Containerfile' -- nodig voor automatische base-image-updates. .dockerignore wordt bovendien (anders dan .containerignore) wel door de docker-CI gebruikt. Workflows, README en de ignore-zelfreferentie bijgewerkt; docker-ecosystem aan dependabot.yml toegevoegd (directory /container).
De container serveerde op root en leunde op het strippen van /kader door de
proxy; daardoor misten redirects de prefix (/kader/x zonder slash -> /x/ -> 404)
en kon de kale /kader niet naar /kader/ redirecten (container zag enkel /).
Nu serveert nginx de prefix zelf via alias + de runtime BASE_PATH:
- location ${BASE_PATH}/ met alias, $uri houdt de volledige prefix -> directory-
redirects behouden /kader;
- bare-prefix redirect /kader -> /kader/ (leeg bij root).
Vereist dat de OpenShift-route /kader ONGESTRIPT doorstuurt (pathType: Prefix,
geen rewrite-target) zodat de container de volledige /kader/... ziet. Gevalideerd
voor zowel root als /kader (incl. beslishulp, canonical/sitemap, 404, dotfiles).
…c naar https: - preview-build-and-deploy: bouw/deploy geen previews voor bot-authored (Dependabot e.d.) of draft-PR's; push naar main blijft bouwen. - CSP img-src: sta elke HTTPS-host toe zodat externe afbeeldingen in content (diagrammen, toegankelijkheidsverklaring-badge) laden zonder per-host allowlist.
There was a problem hiding this comment.
docs/html/beslishulp.html:9 hardcodes data-fontPath="/Algoritmekader/assets/". The RijksSansWeb-*.woff2 files live at docs/assets/, so this only resolves on GitHub Pages (/Algoritmekader). In the container the site is under /kader (or /pr{N}/kader), and sub_filter only rewrites /ak-runtime-base — not /Algoritmekader. So the iframe requests /Algoritmekader/assets/RijksSansWeb-*.woff2 → 404, and the beslishulp falls back to default fonts. This is exactly the base-agnostic goal the rest of the branch achieves, so it stands out.
@uittenbroekrobbert wat denk jij?
|
Dank Ravi — sinds je comment (10 juni) is de routing-aanpak bewust omgedraaid (commit Nieuwe situatie: de container krijgt
Ingress-voorbeeld (nginx-ingress) — zónder rewrite: spec:
rules:
- host: algoritmes.overheid.nl
http:
paths:
- path: /kader
pathType: Prefix
backend: { service: { name: algoritmekader, port: { number: 8080 } } }Health/readiness: let op — met een prefix gezet geeft Onveranderd geldig uit je comment: TLS termineert upstream (container doet alleen HTTP op 8080); de container zet zelf alle security-headers (HSTS, CSP, X-Frame-Options, …) — niet dubbel toevoegen; redirects zijn relatief (trailing-slash blijft binnen Je beslispunt: strippen is dus niet meer aan de orde. De gekozen weg is unstripped doorzetten. De root-variant ( |
github.event.repository.name behoudt de repo-casing (Algoritmekader), maar GHCR slaat de package lowercase op (algoritmekader/preview) en de packages-API is hoofdlettergevoelig. Zonder lowercasen 404't de versions-query, wordt stil ingeslikt door 2>/dev/null en blijven PR-images na sluiten in GHCR staan.
data-fontPath was hardcoded op /Algoritmekader/assets/, wat alleen op GitHub Pages resolvet. In de container (onder /kader of root) gaf dat 404 -> fallback- fonts, want sub_filter herschrijft alleen /ak-runtime-base, niet /Algoritmekader. Met ../assets/ resolvet het pad relatief t.o.v. <base>/html/beslishulp.html en klopt het op elke deployment (gh-pages /Algoritmekader/assets/, container /kader/assets/, root /assets/). Lokaal in de container geverifieerd.
Bundle v1.2.15 leest data-fontPath niet (alleen showCloseOnEnd[Msg], showExportPDF, showExplanationField) en bakt de fonts zelf in als data:font/woff2. Het attribuut deed dus niets; weghalen voorkomt verwarring en een misleidend pad. De overige data-* attributen blijven: die worden wel gelezen.
|
@ravimeijerrig uitgezocht tegen de echte bundle (v1.2.15): de beslishulp bakt z'n fonts zelf in als We hebben het dode |
Summary
container/Dockerfile: MkDocs build + gehardnginx-base(RijksICTGilde, non-root, read-only-rootfs) met security headers (CSP, HSTS, etc.)v*)SITE_URL-env (stuurt interne links/beslishulp éncanonical/sitemap).getBasePath()inmodal.jsleest dit basispad i.p.v. hardcoded paden.Sluit #837
Test plan
docker build -t algoritmekader -f container/Dockerfile .docker run -p 8080:8080 algoritmekader→ http://localhost:8080docker run -e SITE_URL=https://.../kader -p 8080:8080 algoritmekader(reverse proxy stuurt het prefix ongestript door)