ec125261e4
Deploy Vault CMS / deploy (push) Successful in 1m15s
- Build Next.js as a standalone server and copy only that into the runtime image, instead of the whole node_modules tree - Mark three dynamic file reads with turbopackIgnore so the standalone trace does not pull in the entire project - Deploy workflow prunes unused images and build cache older than a day at the start and end of every run, including failed ones, and logs disk usage before building Failed builds were leaving their layers behind until the server's disk filled, which broke the deploy, the database and Gitea sign-in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
65 lines
1.8 KiB
Docker
65 lines
1.8 KiB
Docker
# Multi-stage Dockerfile for Next.js CMS
|
|
# Stage 1: Build
|
|
FROM node:22-alpine AS builder
|
|
|
|
WORKDIR /app
|
|
|
|
# Copy package files
|
|
COPY package.json pnpm-lock.yaml ./
|
|
|
|
# Install dependencies (pnpm pinned so builds are reproducible)
|
|
RUN npm install -g pnpm@10.22.0 && pnpm install --frozen-lockfile
|
|
|
|
# Copy source code
|
|
COPY . .
|
|
|
|
# Refuse to build when a production dependency has a known critical
|
|
# vulnerability. Runs after COPY so it isn't skipped by the layer cache on
|
|
# deploys that only change source code.
|
|
RUN pnpm audit --prod --audit-level critical
|
|
|
|
ARG DATABASE_URL="postgresql://dummy:dummy@localhost:5432/dummy"
|
|
ENV DATABASE_URL=$DATABASE_URL
|
|
|
|
|
|
# Generate Prisma client
|
|
RUN pnpm exec prisma generate
|
|
|
|
# Build Next.js application
|
|
RUN pnpm run build
|
|
|
|
# Stage 2: Production Runtime
|
|
FROM node:22-alpine
|
|
|
|
WORKDIR /app
|
|
|
|
# Install dumb-init for proper signal handling
|
|
RUN apk add --no-cache dumb-init
|
|
|
|
# Copy the standalone server (only the files it actually uses, including the
|
|
# traced parts of node_modules), plus static assets, which it does not include.
|
|
# Files stay root-owned so the app user cannot rewrite its own code; only the
|
|
# Next.js cache directory is writable.
|
|
COPY --from=builder /app/.next/standalone ./
|
|
COPY --from=builder /app/.next/static ./.next/static
|
|
COPY --from=builder /app/public ./public
|
|
RUN mkdir -p .next/cache && chown node:node .next/cache
|
|
|
|
# Set production environment. HOSTNAME makes the server listen on all
|
|
# interfaces rather than only the container's hostname.
|
|
ENV NODE_ENV=production
|
|
ENV HOSTNAME=0.0.0.0
|
|
ENV PORT=3000
|
|
|
|
# Run as the unprivileged "node" user (uid 1000) instead of root
|
|
USER node
|
|
|
|
# Expose port 3000
|
|
EXPOSE 3000
|
|
|
|
# Use dumb-init to handle signals properly
|
|
ENTRYPOINT ["dumb-init", "--"]
|
|
|
|
# Start the standalone Next.js server
|
|
CMD ["node", "server.js"]
|