- express-tools: ExpressServer.serveStaticFrontend() sert le build du frontend (assets + fallback SPA), monté après les routes API et avant le 404 JSON. Opt-in via FRONTEND_DIST_DIR (uniquement défini dans l'image Docker) — le dev natif (dev:api/dev:web) est inchangé. - apps/api/Dockerfile: build aussi apps/web, embarque son dist dans le runtime ; corrige au passage l'oubli de packages/date-tools. Supprime apps/web/Dockerfile et nginx.conf (plus de conteneur nginx séparé). - docker-compose.yml: un seul service "app" (postgres + app), un seul port APP_PORT, plus de WEB_PORT/CORS_ORIGIN à coordonner entre deux origines. Garde `build:` (pas de registre — Portainer build depuis le repo Git). - ci.yml: éclate le job unique lint-and-test+e2e en 4 jobs indépendants (lint/test/build/e2e), sans chaînage, déclenchés sur chaque push (toute branche) + PR vers main. - release.yml (nouveau): sur tag vX.Y.Z, sanity-build de l'image Docker, GitHub Release avec changelog auto-généré, puis notification best-effort du webhook Portainer (secret PORTAINER_WEBHOOK_URL). - README: documente le conteneur unique et le pipeline de release.
47 lines
2.4 KiB
Docker
47 lines
2.4 KiB
Docker
# Debian-based (not alpine) on purpose: avoids musl-vs-glibc native binding
|
|
# surprises for argon2/Prisma's engine binaries. Same base image family for
|
|
# build and runtime stages, so "native" binaries built in `build` are
|
|
# guaranteed compatible with `runtime`.
|
|
FROM node:22-slim AS base
|
|
# Prisma's query engine needs OpenSSL to be present to detect the right
|
|
# binary target; without it, it silently defaults to a guess (openssl-1.1.x)
|
|
# that may not match what's actually on the image and fail at runtime.
|
|
RUN apt-get update && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/*
|
|
RUN corepack enable
|
|
WORKDIR /repo
|
|
|
|
# Single image serving both the API and the built frontend (apps/web) — one
|
|
# process, one container, no separate nginx/static host. Builds both so the
|
|
# runtime stage below can copy each app's build output independently.
|
|
FROM base AS build
|
|
COPY . .
|
|
RUN pnpm install --frozen-lockfile
|
|
RUN pnpm --filter api build
|
|
RUN pnpm --filter web build
|
|
|
|
# Copies the monorepo structure as-is (not a flattened single package) so
|
|
# pnpm's symlinked node_modules (root node_modules/.pnpm <- apps/api/node_modules)
|
|
# stay valid — paths must match exactly between build and runtime stages.
|
|
FROM base AS runtime
|
|
ENV NODE_ENV=production
|
|
# Tells the API where to find the built frontend — see FRONTEND_DIST_DIR's
|
|
# doc comment in apps/api/src/config/env.ts.
|
|
ENV FRONTEND_DIST_DIR=/repo/apps/web/dist
|
|
COPY --from=build /repo/node_modules ./node_modules
|
|
COPY --from=build /repo/package.json ./package.json
|
|
COPY --from=build /repo/pnpm-workspace.yaml ./pnpm-workspace.yaml
|
|
COPY --from=build /repo/packages/shared ./packages/shared
|
|
COPY --from=build /repo/packages/error-tools ./packages/error-tools
|
|
COPY --from=build /repo/packages/express-tools ./packages/express-tools
|
|
COPY --from=build /repo/packages/date-tools ./packages/date-tools
|
|
COPY --from=build /repo/apps/api/node_modules ./apps/api/node_modules
|
|
COPY --from=build /repo/apps/api/dist ./apps/api/dist
|
|
COPY --from=build /repo/apps/api/prisma ./apps/api/prisma
|
|
COPY --from=build /repo/apps/api/package.json ./apps/api/package.json
|
|
COPY --from=build /repo/apps/web/dist ./apps/web/dist
|
|
|
|
WORKDIR /repo/apps/api
|
|
EXPOSE 3000
|
|
# Applies pending migrations before starting — keeps the review environment's
|
|
# schema in sync automatically, no manual step needed.
|
|
CMD ["sh", "-c", "node_modules/.bin/prisma migrate deploy && node dist/server.js"]
|