|
1 | | -# Multi-stage Dockerfile for the monorepo, targeting the Next.js app in apps/v4 |
2 | | -# - Uses pnpm workspaces and Turbo build scripts |
3 | | -# - Builds in a separate stage and runs "next start" on port 4000 |
4 | | - |
5 | | -# syntax=docker/dockerfile:1.6 |
6 | | -ARG NODE_VERSION=24 |
7 | 1 | ARG NEXT_PUBLIC_APP_URL=https://ui.sciol.ac.cn |
| 2 | +ARG NODE_VERSION=24 |
8 | 3 |
|
9 | | -FROM node:${NODE_VERSION}-slim AS base |
10 | | -# Re-declare build args inside the stage to use them in RUN/ENV/etc. |
11 | | -ARG NEXT_PUBLIC_APP_URL |
12 | | -ENV PNPM_HOME=/usr/local/share/pnpm \ |
| 4 | +FROM node:${NODE_VERSION} AS base |
| 5 | +ENV NODE_ENV=production \ |
13 | 6 | NEXT_TELEMETRY_DISABLED=1 \ |
14 | | - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} |
15 | | -ENV PATH="$PNPM_HOME:$PATH" |
16 | | -RUN corepack enable |
| 7 | + PNPM_HOME=/pnpm |
| 8 | +RUN corepack enable \ |
| 9 | + && corepack prepare pnpm@latest --activate |
| 10 | +ENV PATH=$PNPM_HOME:$PATH |
17 | 11 |
|
18 | | -# ------------------------------ |
19 | | -# deps: install workspace deps |
20 | | -# ------------------------------ |
| 12 | +# 1) Install dependencies with maximal cache reuse |
21 | 13 | FROM base AS deps |
22 | 14 | WORKDIR /app |
23 | 15 |
|
24 | | -# Only copy files needed to resolve and fetch deps for better layer caching |
25 | | -COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json tsconfig.json ./ |
26 | | -# Workspace manifests used by the v4 build |
27 | | -COPY apps/v4/package.json apps/v4/package.json |
28 | | -COPY packages/shadcn/package.json packages/shadcn/package.json |
| 16 | +# Only copy lockfile and workspace manifests for better caching |
| 17 | +COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json tsconfig.json ./ |
| 18 | +COPY packages/shadcn/package.json packages/shadcn/ |
| 19 | +COPY packages/tests/package.json packages/tests/ |
| 20 | +COPY apps/v4/package.json apps/v4/ |
29 | 21 |
|
30 | | -# Pre-fetch dependencies to leverage pnpm store cache |
31 | | -RUN pnpm fetch |
| 22 | +# If you have other apps/packages with postinstall/build hooks required for dependency graph, |
| 23 | +# add their package.json similarly above to warm the install cache. |
32 | 24 |
|
33 | | -# Bring in the full repo and link deps |
34 | | -COPY . . |
35 | | -RUN pnpm -w install --frozen-lockfile |
| 25 | +RUN pnpm fetch \ |
| 26 | + && pnpm install --no-frozen-lockfile |
36 | 27 |
|
37 | | -# ------------------------------ |
38 | | -# build: compile the v4 app |
39 | | -# ------------------------------ |
40 | | -FROM deps AS build |
41 | | -ENV NODE_ENV=production \ |
42 | | - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} |
| 28 | +# 2) Build the app |
| 29 | +FROM base AS builder |
43 | 30 | WORKDIR /app |
| 31 | +COPY --from=deps /app /app |
| 32 | + |
| 33 | +ARG NEXT_PUBLIC_APP_URL |
| 34 | +ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL |
| 35 | + |
| 36 | +# Copy the full workspace (respect .dockerignore to keep context small) |
| 37 | +COPY . . |
44 | 38 |
|
45 | | -# Build the local package and then the Next.js app |
46 | | -RUN pnpm --filter=shadcn build \ |
47 | | - && pnpm --filter=v4 build |
| 39 | +# Build the v4 app (its script builds workspace package "shadcn" first) |
| 40 | +RUN pnpm --filter v4 build |
| 41 | + |
| 42 | +# 3) Create a minimal deployable directory for the v4 app with only prod deps |
| 43 | +# This leverages pnpm deploy to gather exactly what's needed to run the app |
| 44 | +FROM base AS deployer |
| 45 | +WORKDIR /app |
| 46 | +COPY --from=builder /app /app |
48 | 47 |
|
49 | | -# ------------------------------ |
50 | | -# runner: minimal runtime image |
51 | | -# ------------------------------ |
52 | | -FROM node:${NODE_VERSION}-slim AS runner |
53 | | -# Re-declare to make the arg available in this stage as well |
54 | 48 | ARG NEXT_PUBLIC_APP_URL |
55 | | -ENV NODE_ENV=production \ |
56 | | - NEXT_TELEMETRY_DISABLED=1 \ |
57 | | - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} |
| 49 | +ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL |
| 50 | + |
| 51 | +# Prune to production-only files for the v4 application |
| 52 | +RUN pnpm deploy --filter v4 --prod /runtime |
58 | 53 |
|
59 | | -# Use a non-root user for security |
60 | | -USER node |
| 54 | +# 4) Final runtime image |
| 55 | +FROM node:${NODE_VERSION} AS runner |
| 56 | +ENV NODE_ENV=production \ |
| 57 | + NEXT_TELEMETRY_DISABLED=1 |
61 | 58 | WORKDIR /app |
62 | 59 |
|
63 | | -# Copy standalone output only (no pnpm/npm needed in runtime) |
64 | | -# Next.js standalone contains the server and minimal node_modules tree |
65 | | -COPY --chown=node:node --from=build /app/apps/v4/.next/standalone ./ |
66 | | -COPY --chown=node:node --from=build /app/apps/v4/.next/static ./apps/v4/.next/static |
67 | | -COPY --chown=node:node --from=build /app/apps/v4/public ./apps/v4/public |
| 60 | +ARG NEXT_PUBLIC_APP_URL |
| 61 | +ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL |
| 62 | + |
68 | 63 |
|
69 | | -# Expose the v4 app port |
| 64 | +# Bring in the pruned app produced by pnpm deploy |
| 65 | +COPY --from=deployer /runtime /app |
| 66 | + |
| 67 | +# Expose the port used by apps/v4 (see scripts:start) |
70 | 68 | EXPOSE 3000 |
71 | 69 |
|
72 | | -# Run the standalone server |
| 70 | +# Switch to the app workspace and drop privileges |
73 | 71 | WORKDIR /app/apps/v4 |
74 | | -CMD ["node", "server.js"] |
| 72 | + |
| 73 | +# Start Next.js in production |
| 74 | +CMD ["node", "node_modules/next/dist/bin/next", "start", "-p", "3000"] |
0 commit comments