Files
TehRiehlBudget/tehriehlbudget-frontend/Dockerfile
T
TehRiehlDeal bac97674a1
CI / test (push) Successful in 25s
CI / lint (push) Successful in 27s
CI / secrets-scan (push) Successful in 5s
CI / vuln-scan (push) Successful in 13s
CI / sast (push) Successful in 11s
CI / build-images (push) Successful in 1m47s
CI / push (push) Successful in 30s
CI / image-scan (push) Successful in 43s
Make the deployed images actually run
Two production-only failures the CI scan didn't catch:

Backend: the running container was crashing with `Cannot find module
'/app/dist/main'`. nest build was emitting `dist/src/main.js` instead
of `dist/main.js` because tsconfig.json had no rootDir, so tsc inferred
it as `.` and preserved the src/ subdirectory in the output. Set
`rootDir: "./src"` to flatten the output. Also exclude prisma/ from
tsconfig.build.json so prisma/seed.ts (a ts-node script that lives
outside src/) doesn't trip the rootDir check during builds.

Frontend: containers came up but were marked unhealthy because the
deployment's healthcheck targeted port 80 — which nginx-unprivileged
can't bind. Add a HEALTHCHECK directive to the image pointing at 8080
so any orchestrator inherits a working default. Compose-level
overrides still need to be updated independently.

Also clean up build-artifact gitignore patterns: *.tsbuildinfo and
compiled prisma/seed.* (a stale tsc invocation against the old
build config emitted them locally; they shouldn't ever be committed).

Bump backend and frontend to 0.1.3 — the broken 0.1.2 images are now
occupying those tags in Harbor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 17:45:41 -07:00

39 lines
2.0 KiB
Docker

# syntax=docker/dockerfile:1.7
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine AS deps
RUN corepack enable && corepack prepare pnpm@9 --activate
WORKDIR /repo
COPY pnpm-workspace.yaml pnpm-lock.yaml package.json ./
COPY tehriehlbudget-backend/package.json tehriehlbudget-backend/
COPY tehriehlbudget-frontend/package.json tehriehlbudget-frontend/
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store \
pnpm install --frozen-lockfile --filter tehriehlbudget-frontend...
FROM deps AS build
WORKDIR /repo
COPY tehriehlbudget-frontend/ tehriehlbudget-frontend/
# Build with no VITE_* env: import.meta.env values resolve to "" so the bundle
# carries no compile-time secrets. window.__RUNTIME_CONFIG__ supplies them.
RUN pnpm --filter tehriehlbudget-frontend run build
FROM nginxinc/nginx-unprivileged:1.27-alpine AS runtime
USER root
# Pull current Alpine package patches before adding anything else. The
# base image lags behind upstream Alpine's security backports (openssl,
# libxml2, libpng, musl, etc. were all flagged HIGH/CRITICAL on the
# stock 3.21.3 packages). `apk upgrade` picks up the fixed -r versions
# without bumping the nginx version itself.
RUN apk upgrade --no-cache && apk add --no-cache gettext
COPY --from=build --chown=nginx:nginx /repo/tehriehlbudget-frontend/dist /usr/share/nginx/html
COPY --chown=nginx:nginx tehriehlbudget-frontend/nginx.conf /etc/nginx/conf.d/default.conf
COPY --chown=nginx:nginx tehriehlbudget-frontend/docker-entrypoint.sh /docker-entrypoint.d/40-render-config.sh
RUN chmod +x /docker-entrypoint.d/40-render-config.sh
USER nginx
EXPOSE 8080
# nginx-unprivileged can't bind privileged ports; the image listens on 8080,
# so a healthcheck targeting :80 will always fail. Bake in a sensible default
# that any orchestrator (compose, k8s, Portainer) inherits unless overridden.
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget -qO /dev/null http://127.0.0.1:8080/ || exit 1