22ARG NODE_VERSION=22
33
44# =================================================================================================
5- # 1. Builder Stage: Installs all dependencies, builds the source code, and prunes dev dependencies .
5+ # 1. Builder Stage: Installs all dependencies and builds the source code.
66# =================================================================================================
77FROM node:${NODE_VERSION}-slim AS builder
88
99# Set environment variables for pnpm
1010ENV PNPM_HOME="/pnpm"
1111ENV PATH="$PNPM_HOME:$PATH"
12- # Use corepack to install pnpm, which is the recommended method since Node.js v16.13
13- RUN corepack enable && corepack prepare pnpm@9.9.0 --activate
12+ RUN corepack enable && corepack prepare pnpm@latest --activate
1413
1514WORKDIR /usr/src/app
1615
17- # 🛠 Install OpenSSL and build tools needed for native modules (like Prisma)
16+ # Install build tools needed for native modules (like Prisma)
1817RUN apt-get update && apt-get install -y --no-install-recommends \
1918 openssl \
2019 libssl-dev \
@@ -23,37 +22,36 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
2322 python3 \
2423 && rm -rf /var/lib/apt/lists/*
2524
26- # Copy only the files required to install dependencies.
27- # This maximizes layer caching. The install step will only re-run if these files change.
25+ # Copy files required to install dependencies to maximize layer caching
2826COPY pnpm-lock.yaml pnpm-workspace.yaml ./
29- COPY package.json tsconfig.json turbo.json ./
27+ COPY package.json ./
3028COPY packages/ packages/
3129COPY apps/api/package.json apps/api/
3230
33- # Use `pnpm fetch` to download dependencies into a shared content-addressable store.
34- # This creates a highly cacheable layer.
31+ # Use `pnpm fetch` to download all dependencies into a shared store.
3532RUN pnpm fetch
3633
34+ # Install all dependencies (including devDependencies) using the fetched packages
35+ RUN pnpm install --frozen-lockfile --offline
36+
3737# Copy the rest of the source code
3838COPY . .
3939
40- # Install dependencies using the fetched packages (offline) and generate Prisma client
41- RUN pnpm install --frozen-lockfile --offline
40+ # Generate Prisma client
4241RUN pnpm db:generate
4342
4443# Build the specific 'api' application
4544RUN pnpm build --filter=api
4645
47- # Prune development dependencies to reduce the size of the node_modules folder
48- RUN pnpm prune --prod
49-
5046# =================================================================================================
5147# 2. Production Stage: Creates the final, small, and secure image.
5248# =================================================================================================
5349FROM node:${NODE_VERSION}-slim AS production
5450
55- # Set the environment to production
5651ENV NODE_ENV=production
52+ ENV PNPM_HOME="/pnpm"
53+ ENV PATH="$PNPM_HOME:$PATH"
54+ RUN corepack enable && corepack prepare pnpm@latest --activate
5755
5856WORKDIR /usr/src/app
5957
@@ -62,27 +60,36 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
6260 openssl \
6361 && rm -rf /var/lib/apt/lists/*
6462
65- # Create a non-root user and group for security
63+ # Create a non-root user for security
6664RUN addgroup --system --gid 1001 nodejs
6765RUN adduser --system --uid 1001 nodejs
6866
69- # Copy pruned dependencies, built code, and necessary package files from the builder stage
70- # --chown sets the correct permissions for our non-root user
71- COPY --from=builder --chown=nodejs:nodejs /usr/src/app/node_modules ./node_modules
72- COPY --from=builder --chown=nodejs:nodejs /usr/src/app/pnpm-lock.yaml ./pnpm-lock.yaml
67+ # === THE KEY CHANGE IS HERE ===
68+ # Instead of copying the pruned node_modules, we will reinstall only production dependencies.
69+
70+ # First, copy over the necessary package manifests and lockfile from the builder
71+ COPY --from=builder /usr/src/app/pnpm-lock.yaml ./
72+ COPY --from=builder /usr/src/app/pnpm-workspace.yaml ./
73+ COPY --from=builder /usr/src/app/package.json ./
74+ COPY --from=builder /usr/src/app/packages/ packages/
75+ COPY --from=builder /usr/src/app/apps/api/package.json apps/api/
76+
77+ # Now, install ONLY production dependencies using the packages already fetched by the builder stage.
78+ # This creates a clean, production-only node_modules folder.
79+ RUN pnpm install --prod --frozen-lockfile --offline
80+
81+ # Copy the built application code and Prisma schema from the builder stage
7382COPY --from=builder --chown=nodejs:nodejs /usr/src/app/apps/api/dist ./apps/api/dist
74- COPY --from=builder --chown=nodejs:nodejs /usr/src/app/apps/api/package.json ./apps/api/package.json
75- # Prisma client also needs access to the schema file at runtime
7683COPY --from=builder --chown=nodejs:nodejs /usr/src/app/packages/db/prisma ./apps/api/prisma
84+
7785# Switch to the non-root user
7886USER nodejs
7987
8088# Change to the app-specific directory
8189WORKDIR /usr/src/app/apps/api
8290
83- # Expose the port your app runs on (replace 3000 if different)
91+ # Expose the port your app runs on
8492EXPOSE 5000
8593
86- # Start the application directly with node, avoiding the need for pnpm in the final image.
87- # Assumes your start script runs `node dist/main.js` or similar.
94+ # Start the application
8895CMD ["node", "dist/index.js"]
0 commit comments