# syntax=docker/dockerfile:1.7 # -------- Base image -------- FROM node:22-bookworm-slim AS base WORKDIR /app # Enable corepack for pnpm/yarn RUN corepack enable # Install OS deps RUN apt-get update && apt-get install -y --no-install-recommends openssl ca-certificates && rm -rf /var/lib/apt/lists/* # -------- Install all dependencies (dev) -------- FROM base AS deps # Copy only manifest files for better caching COPY package.json pnpm-lock.yaml* yarn.lock* package-lock.json* ./ # Install deps (prefer pnpm if lock exists) RUN if [ -f pnpm-lock.yaml ]; then corepack prepare pnpm@latest --activate && pnpm install --frozen-lockfile; \ elif [ -f yarn.lock ]; then yarn install --frozen-lockfile; \ else npm ci; fi # -------- Build source -------- FROM base AS build ENV NODE_ENV=development COPY --from=deps /app/node_modules ./node_modules COPY . . COPY prisma ./prisma # Generate Prisma client and build RUN npx prisma generate RUN if [ -f pnpm-lock.yaml ]; then pnpm build; \ elif [ -f yarn.lock ]; then yarn build; \ else npm run build; fi # -------- Production dependencies only -------- FROM base AS prod-deps ENV NODE_ENV=production \ HUSKY=0 COPY package.json pnpm-lock.yaml* yarn.lock* package-lock.json* ./ RUN if [ -f pnpm-lock.yaml ]; then corepack prepare pnpm@latest --activate && pnpm install --frozen-lockfile --ignore-scripts; \ elif [ -f yarn.lock ]; then yarn install --frozen-lockfile --production=true --ignore-scripts; \ else npm ci --omit=dev --ignore-scripts; fi # -------- Runtime image -------- FROM base AS runner ARG PORT=4000 ENV NODE_ENV=production \ HUSKY=0 \ PORT=${PORT} WORKDIR /app # Non-root user RUN groupadd -g 1001 nodejs && useradd -u 1001 -g nodejs -s /bin/bash -m nest # Copy runtime artifacts COPY ./commit-sha.txt ./ COPY --from=prod-deps /app/node_modules ./node_modules COPY --from=build /app/package.json ./ COPY --from=build /app/commit-sha.txt ./ COPY --from=build /app/ecosystem.config.js ./ COPY --from=build /app/dist ./dist COPY --from=build /app/static ./static COPY --from=build /app/prisma ./prisma # you need this for components COPY --from=build /app/src/components ./src/components # Remove unnecessary sources from runtime image to reduce size # (src is not required at runtime; prisma schema is needed for generate only) # Keep only what start:prod needs # Generate Prisma client in runtime stage to ensure correct paths RUN npx prisma generate # Create adminjs directory and set proper ownership for the nest user RUN mkdir -p .adminjs && chown -R 1001:1001 /app/.adminjs USER 1001 EXPOSE ${PORT} CMD ["npm", "run", "start:prod"] # -------- Migrate image (one-shot) -------- FROM base AS migrate ENV NODE_ENV=production WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Generate prisma client (safe even if already generated) RUN npx prisma generate # Default command runs migrations against DATABASE_URL CMD ["npx", "prisma", "migrate", "deploy"] # -------- Dev image (watch mode) -------- FROM deps AS dev ARG PORT=4000 ENV NODE_ENV=development \ PORT=${PORT} WORKDIR /app COPY . . RUN npx prisma generate EXPOSE ${PORT} CMD ["npm", "run", "start:dev"]