mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-13 18:27:40 +02:00
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:
5 files changed
+146
-101
No files matched your search
+14
-38
@@ -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*
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user