Docker : image Rust + SPA publiée sur GHCR, tirée au démarrage

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LG2LLJuswrrTTPKJmunEVf
This commit is contained in:
Claude committed 2026-10-12 19:02:45 +00:00
1 parent a878270081
commit 87d5803b55
5 files changed
+146 -101

No files matched your search

+14 -38
View File
@@ -1,38 +1,14 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
# BMad and Antigravity
_bmad-output/
.gemini/
.antigravityignore
.git
.github
.claude
.agent
.agents
_bmad
_bmad-output
node_modules
dist
data
server/target
*.md
!README.md
.env*
+36
View File
@@ -0,0 +1,36 @@
name: CI
# Vérifie le serveur Rust et l'interface sur chaque pull request.
on:
pull_request:
push:
branches: [main]
jobs:
server:
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- uses: Swatinem/rust-cache@v2
with:
workspaces: server
- run: cargo build --locked
- run: cargo test --locked
web:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run build
+44
View File
@@ -0,0 +1,44 @@
name: Image Docker
# Construit l'image à chaque mise à jour de main et la publie sur GHCR :
# le serveur la récupère au prochain `docker compose up -d` (pull_policy: always).
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
packages: write
concurrency:
group: docker-publish
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Nom de l'image (minuscules)
id: image
run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT"
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
${{ steps.image.outputs.name }}:latest
${{ steps.image.outputs.name }}:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
+45 -57
View File
@@ -1,70 +1,58 @@
FROM node:20-alpine AS base
# CollectFlow — image de production.
#
# 1. web : compile l'interface React (Vite) en fichiers statiques.
# 2. server : compile le serveur Rust (binaire unique, optimisé).
# 3. runner : Debian minimale + Chromium (extraction Qlik) + les deux livrables.
#
# L'image est construite et publiée par GitHub Actions à chaque push sur main
# (ghcr.io/r0m1k3/collectflow:latest) ; docker-compose la tire au démarrage.
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN apk add --no-cache libc6-compat
# ---------------------------------------------------------------------------
FROM node:22-alpine AS web
WORKDIR /app
# Install dependencies based on the preferred package manager
COPY package.json package-lock.json* ./
RUN npm ci
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY package.json package-lock.json ./
RUN npm ci --no-audit --no-fund
COPY . .
# Next.js telemetry is disabled
ENV NEXT_TELEMETRY_DISABLED=1
# Limit workers and increase memory to prevent OOM
ENV NODE_OPTIONS="--max-old-space-size=4096"
ENV NEXT_PRIVATE_WORKER_THREADS=0
RUN npm run build
# Production image, copy all the files and run next
FROM base AS runner
# ---------------------------------------------------------------------------
FROM rust:1-bookworm AS server
WORKDIR /build
# Dépendances d'abord : couche réutilisée tant que Cargo.lock ne change pas.
COPY server/Cargo.toml server/Cargo.lock ./
RUN mkdir src && echo "fn main() {}" > src/main.rs \
&& cargo build --release --locked \
&& rm -rf src target/release/deps/collectflow* target/release/collectflow*
COPY server/ ./
RUN cargo build --release --locked && cp target/release/collectflow /collectflow
# ---------------------------------------------------------------------------
FROM debian:bookworm-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
# Next.js telemetry is disabled
ENV NEXT_TELEMETRY_DISABLED=1
# Chromium pour l'extraction Qlik (websocket Engine ouvert dans la page) + polices.
RUN apt-get update \
&& apt-get install -y --no-install-recommends chromium ca-certificates fonts-liberation fonts-freefont-ttf tzdata \
&& rm -rf /var/lib/apt/lists/*
# Chromium pour l'extraction Qlik via Playwright (ws in-page) + dépendances headless
RUN apk add --no-cache chromium nss freetype harfbuzz ca-certificates ttf-freefont
ENV PLAYWRIGHT_CHROMIUM_PATH=/usr/bin/chromium-browser
# Même UID/GID que l'ancienne image Node : le volume /app/data existant reste lisible.
RUN groupadd --system --gid 1001 collectflow \
&& useradd --system --uid 1001 --gid collectflow --home-dir /app collectflow \
&& mkdir -p /app/data \
&& chown -R collectflow:collectflow /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=server /collectflow /app/collectflow
COPY --from=web --chown=collectflow:collectflow /app/dist /app/web
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache and data storage
RUN mkdir .next data
RUN chown nextjs:nodejs .next data
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# playwright-core n'est pas toujours tracé par le standalone — on le copie explicitement
COPY --from=deps --chown=nextjs:nodejs /app/node_modules/playwright-core ./node_modules/playwright-core
# Grant write access to /app for settings persistence
RUN chown -R nextjs:nodejs /app
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
USER nextjs
ENV PORT=5643 \
HOSTNAME=0.0.0.0 \
DATA_DIR=/app/data \
STATIC_DIR=/app/web \
PLAYWRIGHT_CHROMIUM_PATH=/usr/bin/chromium \
RUST_LOG=info
USER collectflow
EXPOSE 5643
VOLUME ["/app/data"]
ENV PORT=5643
# set hostname to localhost
ENV HOSTNAME="0.0.0.0"
# Run the DB init script, then start the standalone server
CMD node scripts/db-init.js && node server.js
CMD ["/app/collectflow"]
+7 -6
View File
@@ -1,20 +1,21 @@
version: "3.8"
services:
web:
# Image publiée par GitHub Actions à chaque mise à jour de main.
# `pull_policy: always` : chaque `docker compose up -d` récupère la
# dernière version avant de (re)démarrer le conteneur.
image: ghcr.io/r0m1k3/collectflow:latest
pull_policy: always
# Construction locale possible : `docker compose build` (utilise le Dockerfile).
build:
context: .
dockerfile: Dockerfile
ports:
- "5643:5643"
environment:
- NODE_ENV=production
- AUTH_TRUST_HOST=true
- AUTH_SECRET=my-super-secret-key-that-should-be-changed-in-production
- DATABASE_URL=postgres://postgres:MOT_DE_PASSE_ICI@postgresbase:5432/collectflow
- FF_API_BASE_URL=https://api.ffnancy.fr
# Mais comme CollectFlow permet de le configurer depuis l'interface (settings), ce n'est pas strictement obligatoire au lancement.
# La base, Qlik et l'API FF se règlent aussi depuis l'interface (Paramètres).
volumes:
- collectflow-data:/app/data
restart: unless-stopped