ci(docker): versioned image builds + Gitea build/push workflow
Add comprehensive Docker image versioning and a Gitea Actions workflow that builds and pushes both the API and web images to the git.mancinas.io registry. Versioning: both Dockerfiles take APP_VERSION / GIT_SHA / BUILD_DATE build-args, surfaced as runtime ENV + OCI labels, so a running container self-reports the exact commit it was built from. metadata-action emits a tag set per build: semver (from vX.Y.Z git tags), branch ref, sha-<short>, and latest (default branch only). Also fix the Dockerfiles for the pnpm workspace: the old npm install could not resolve the "@jorgecuadros/database": "workspace:*" protocol dep and would abort the API build. Now pin pnpm 9.15.9 via corepack, install --frozen-lockfile with node-linker=hoisted (flat tree so the runtime stage copies a single node_modules), and build via --filter. The API build stage gets python3/make/g++ for argon2's musl source compile. Add .dockerignore to keep the build context lean and deterministic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+49
-4
@@ -1,24 +1,69 @@
|
||||
FROM node:20-alpine AS base
|
||||
WORKDIR /repo
|
||||
# Pin pnpm 9 to match pnpm-lock.yaml (lockfileVersion 9.0). pnpm 9 runs
|
||||
# dependency build scripts automatically (the v10 build-allowlist gating does
|
||||
# not apply), so argon2's native addon + prisma engines build without extra
|
||||
# approval config.
|
||||
RUN corepack enable && corepack prepare pnpm@9.15.9 --activate
|
||||
|
||||
FROM base AS deps
|
||||
COPY package.json package-lock.json* ./
|
||||
# argon2's native addon has no musl prebuild -> compiles from source here.
|
||||
RUN apk add --no-cache python3 make g++
|
||||
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
|
||||
COPY apps/api/package.json apps/api/package.json
|
||||
COPY apps/web/package.json apps/web/package.json
|
||||
COPY packages/database/package.json packages/database/package.json
|
||||
RUN npm install --workspace=packages/database --workspace=apps/api --no-audit --no-fund
|
||||
# node-linker=hoisted flattens the store into a single npm-style /repo/node_modules
|
||||
# so the runtime stage can copy one tree (pnpm's default symlinked layout would
|
||||
# break across COPY stages).
|
||||
RUN pnpm install --frozen-lockfile --config.node-linker=hoisted
|
||||
|
||||
FROM deps AS build
|
||||
COPY packages/database packages/database
|
||||
COPY apps/api apps/api
|
||||
RUN npm run generate -w packages/database
|
||||
RUN npm run build -w apps/api
|
||||
RUN pnpm --filter @jorgecuadros/database generate
|
||||
RUN pnpm --filter @jorgecuadros/api build
|
||||
|
||||
FROM node:20-alpine AS runtime
|
||||
WORKDIR /repo
|
||||
ENV NODE_ENV=production
|
||||
|
||||
# DB-ops toolchain baked in so the "Operaciones" admin panel can run backups
|
||||
# (mysqldump), restores (mysql), and the re-import pipeline (python + mdbtools)
|
||||
# from inside the API container. Build deps are installed in a throwaway virtual
|
||||
# package so pandas/pyarrow build on musl, then dropped from the final layer.
|
||||
RUN apk add --no-cache python3 mdbtools mysql-client \
|
||||
&& apk add --no-cache --virtual .pybuild python3-dev build-base \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
COPY --from=build /repo/node_modules node_modules
|
||||
COPY --from=build /repo/packages/database packages/database
|
||||
COPY --from=build /repo/apps/api/dist apps/api/dist
|
||||
COPY --from=build /repo/apps/api/package.json apps/api/package.json
|
||||
|
||||
# Migration scripts + their own Python venv (ops.service.ts prefers this venv).
|
||||
COPY migration migration
|
||||
RUN python3 -m venv migration/.venv \
|
||||
&& migration/.venv/bin/pip install --no-cache-dir -r migration/requirements.txt \
|
||||
&& apk del .pybuild
|
||||
|
||||
# Ingest (uploaded Access files) and backups live on mounted volumes.
|
||||
ENV MIGRATION_DIR=/repo/migration \
|
||||
INGEST_DIR=/data/ingest \
|
||||
BACKUP_DIR=/data/backups \
|
||||
MIGRATION_ENV=dev
|
||||
RUN mkdir -p /data/ingest /data/backups
|
||||
|
||||
# Build/version metadata baked in at image build time (see .gitea/workflows/build.yml).
|
||||
# APP_VERSION is the metadata-action primary tag (semver tag, branch, or sha);
|
||||
# GIT_SHA/BUILD_DATE pin the exact commit + build instant. Exposed as ENV so a
|
||||
# running container can self-report what is deployed (e.g. a /version endpoint).
|
||||
ARG APP_VERSION=dev
|
||||
ARG GIT_SHA=unknown
|
||||
ARG BUILD_DATE=unknown
|
||||
ENV APP_VERSION=$APP_VERSION \
|
||||
GIT_SHA=$GIT_SHA \
|
||||
BUILD_DATE=$BUILD_DATE
|
||||
|
||||
EXPOSE 3001
|
||||
CMD ["node", "apps/api/dist/main.js"]
|
||||
|
||||
Reference in New Issue
Block a user