Skip to content

feat(docker): image nginx + publication GHCR sur tag#44

Merged
BartM82 merged 5 commits into
mainfrom
feat/docker-image
May 16, 2026
Merged

feat(docker): image nginx + publication GHCR sur tag#44
BartM82 merged 5 commits into
mainfrom
feat/docker-image

Conversation

@sebdraven

Copy link
Copy Markdown
Member

Summary

Ajoute une image Docker prete pour la prod qui sert la SPA via nginx, plus la CI qui la publie sur GHCR.

docker/Dockerfile (multi-stage)

  • Stage 1 (python:3.12-alpine) : regenere docs/data/*.json depuis les .md sources via dima_convert.py (stdlib only, aucune dependance). L'image est ainsi autocoherente : pas besoin que les JSON soient a jour dans le commit.
  • Stage 2 (nginxinc/nginx-unprivileged:alpine) : sert docs/ sur le port 8080 (non-root).
  • HEALTHCHECK : ping de / toutes les 30 s.
  • Labels OCI (titre, description, source).

docker/nginx.conf

  • gzip on (text/json/css/js/svg).
  • Cache-Control: no-cache, must-revalidate pour .html et .json (un redeploiement se voit tout de suite).
  • Cache-Control: max-age=2592000, immutable pour les assets type fonts/images.
  • Fallback try_files $uri $uri/ /index.html.

.github/workflows/docker.yml

  • Tag v* : build multi-arch (linux/amd64 + linux/arm64) puis push GHCR avec deux tags : la version du git tag ET latest.
  • PR touchant docker/** : build-only (no push), pour valider que le Dockerfile compile encore.
  • workflow_dispatch : run manuel.
  • Cache type=gha actif pour des rebuilds rapides.

Premier usage

docker run --rm -p 8080:8080 ghcr.io/m82-project/dima:latest
# puis ouvrir http://localhost:8080

A faire apres le premier push d'image

  • Dans Packages sur GitHub, rendre l'image public (sinon GHCR demande une authentification au pull).
  • Optionnel : lier le package au repo DIMA dans ses settings.

Test plan

  • CI : le job build passe sur cette PR (build-only).
  • Apres merge + tag v1.0.0, verifier que ghcr.io/m82-project/dima:v1.0.0 et :latest existent.
  • docker run --rm -p 8080:8080 ghcr.io/m82-project/dima:latest et tester la SPA dans le navigateur (recherche, panneau detail, bouton PDF, rapport de campagne).

Generated with Claude Code

sebdraven and others added 3 commits May 15, 2026 22:59
Adds a multi-stage Dockerfile (docker/Dockerfile):
- Stage 1 (python:3.12-alpine) regenerates docs/data/*.json from the
  per-phase Markdown via the stdlib-only dima_convert.py.
- Stage 2 (nginxinc/nginx-unprivileged:alpine) serves the result on
  port 8080 with a custom nginx.conf: gzip, no-cache for html/json,
  long cache for static assets, SPA fallback, autoindex off.
- HEALTHCHECK pings /index.html every 30 s.

Workflow .github/workflows/docker.yml builds and pushes a multi-arch
image (linux/amd64 + linux/arm64) to GHCR:
- on git tag push (v*): publishes <tag> AND latest;
- on pull_request touching docker/**: build-only (no push) for safety;
- on workflow_dispatch: manual run.

Uses gha cache to keep rebuilds fast.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits the two image streams so they never overwrite each other:

- push to main (default branch)  -> ghcr.io/.../dima:latest
- push of a git tag v*           -> ghcr.io/.../dima:<tag>

A tagged release no longer touches :latest, and a regular merge into
main no longer waits for a tag to refresh :latest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a tests stage to the Dockerfile alongside the existing nginx
runtime. The stage installs pytest, copies the source and the four
phase markdown files, then runs the suite as part of the build so a
failing test breaks `docker build --target tests`. CMD points at
pytest so the image is also usable as `docker run --rm <image>`.

The Docker workflow gains a second job that builds and publishes this
test image, tagged with the same scheme as the runtime image plus a
-tests suffix:

  main push    -> ghcr.io/.../dima:latest        + :latest-tests
  v1.2.3 push  -> ghcr.io/.../dima:v1.2.3        + :v1.2.3-tests

The test image is amd64-only (no need to emulate arm64 just to run
pytest) and uses its own GHA cache scope. Both jobs only push outside
PRs; on PR they only build, which still triggers the in-build pytest
run via the tests stage and therefore catches regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Cette PR ajoute une image Docker “production” basée sur nginx pour servir la SPA contenue dans docs/, ainsi qu’un workflow GitHub Actions pour builder et publier l’image sur GHCR.

Changes:

  • Ajout d’un Dockerfile multi-stage : régénération des JSON depuis les Markdown puis image runtime nginx unprivileged sur le port 8080.
  • Ajout d’une config nginx (gzip, politiques de cache, fallback SPA).
  • Ajout d’un workflow CI pour build multi-arch et push sur GHCR (plus une image “tests” ciblant pytest).

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
docker/nginx.conf Configuration nginx pour servir la SPA avec compression, cache headers et fallback index.html.
docker/Dockerfile Build multi-stage : génération JSON (builder), exécution pytest (target tests), runtime nginx.
.github/workflows/docker.yml CI Docker : build multi-arch runtime + build tests, push GHCR selon événements.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread docker/nginx.conf
Comment thread .github/workflows/docker.yml
Comment thread .github/workflows/docker.yml
Comment thread docker/Dockerfile Outdated
Comment thread .github/workflows/docker.yml
Comment thread .github/workflows/docker.yml
Five fixes raised by the Copilot review on this PR:

- Switch both builder and tests stages to ghcr.io/astral-sh/uv:python3.12-alpine
  and drop `pip install pytest`. The tests stage now runs `uv sync --group dev`
  to pick up pytest with the version range pinned in pyproject.toml, then
  `uv run pytest` to execute it. Same toolchain (uv) everywhere.
- nginx: re-apply Cache-Control: no-cache to the SPA fallback in `location /`
  so that /index.html served on unknown routes (e.g. /campaign/123) doesn't
  silently sit in a downstream cache after a redeploy.
- workflow: add a `type=sha,prefix=sha-` fallback tag enabled on
  workflow_dispatch, and guard the build-push step with
  `steps.meta.outputs.tags != ''`, so a manual run from a non-default branch
  never tries to push with no tag.
- New .dockerignore keeping .git/, the LaTeX article/, the published PDF,
  plugin/, misp/, .claude/ and various caches out of the build context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread .github/workflows/docker.yml
Comment thread .github/workflows/docker.yml
Comment thread docker/Dockerfile Outdated
Comment thread .github/workflows/docker.yml
Two remaining Copilot remarks:

- Commit uv.lock and drop the .gitignore entry for it. The tests stage
  now does `uv sync --group dev --frozen`, so rebuilding the test image
  from the same commit always resolves the exact pytest version that
  passed CI (pytest>=8 alone could otherwise drift).
- Extend the docker.yml pull_request path filter to also watch docs/**
  and pyproject.toml (and uv.lock now that it's tracked). Both feed
  into the Docker build (COPY docs/ in runtime, uv sync in tests), so a
  PR touching only the SPA assets or dependency config should still
  validate the Docker build.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sebdraven
sebdraven requested a review from BartM82 May 15, 2026 22:36
@BartM82
BartM82 merged commit 2dbe2af into main May 16, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants