From a9d6ac030523a3c18ba37f3b9a312860f586ff24 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Sun, 28 Dec 2025 11:20:33 -0300 Subject: [PATCH] perf(docker): migrate frontend to pnpm + optimize dockerignore - Migrate from npm to pnpm for 2-3x faster installs - Add BuildKit cache mount for pnpm store - Auto-import package-lock.json to pnpm-lock.yaml - Reduce NODE_OPTIONS memory to 512MB - Add more exclusions to .dockerignore (cypress, e2e, tests) - Cleanup caches in same layer to save disk --- frontend/.dockerignore | 19 +++++++++++ frontend/Dockerfile | 72 +++++++++++++++++++++++++++--------------- 2 files changed, 66 insertions(+), 25 deletions(-) diff --git a/frontend/.dockerignore b/frontend/.dockerignore index 1f61406..9d9f37b 100644 --- a/frontend/.dockerignore +++ b/frontend/.dockerignore @@ -8,11 +8,19 @@ node_modules/ out/ build/ dist/ +.turbo/ # Testing coverage/ .nyc_output/ *.lcov +cypress/ +e2e/ +__tests__/ +*.test.ts +*.test.tsx +*.spec.ts +*.spec.tsx # IDE and editor .idea/ @@ -28,6 +36,7 @@ coverage/ # Documentation *.md LICENSE +docs/ # Environment files (security) .env @@ -43,6 +52,7 @@ yarn-error.log* # TypeScript cache *.tsbuildinfo +next-env.d.ts # OS files .DS_Store @@ -50,7 +60,16 @@ Thumbs.db # Storybook storybook-static/ +.storybook/ + +# Docker (prevent recursion) +Dockerfile* +docker-compose* +.dockerignore # Misc *.pem +*.key .vercel +.eslintcache + diff --git a/frontend/Dockerfile b/frontend/Dockerfile index c883232..a2b81df 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,62 +1,84 @@ # ============================================================================= -# GoHorse Jobs Frontend - Optimized Production Dockerfile +# GoHorse Jobs Frontend - Ultra-Optimized Dockerfile with pnpm +# Target: < 150MB final image, minimal disk usage during build # ============================================================================= # syntax=docker/dockerfile:1 # ----------------------------------------------------------------------------- -# Stage 1: Dependencies +# Stage 1: Base with pnpm # ----------------------------------------------------------------------------- -FROM mirror.gcr.io/library/node:20-alpine AS deps +FROM mirror.gcr.io/library/node:20-alpine AS base + +# Enable corepack and activate pnpm (latest) +RUN corepack enable && corepack prepare pnpm@latest --activate + +# Set pnpm store for caching +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" + +# ----------------------------------------------------------------------------- +# Stage 2: Dependencies +# ----------------------------------------------------------------------------- +FROM base AS deps WORKDIR /app -# Install ALL dependencies (dev + prod) for build stage -COPY package.json package-lock.json* ./ -RUN --mount=type=cache,target=/root/.npm \ - npm ci && npm cache clean --force +# Copy package files (pnpm will use package-lock.json if no pnpm-lock.yaml) +COPY package.json package-lock.json* pnpm-lock.yaml* ./ + +# Install deps with cache mount - dramatically reduces disk usage on rebuilds +RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ + pnpm import 2>/dev/null || true && \ + pnpm install --frozen-lockfile || pnpm install # ----------------------------------------------------------------------------- -# Stage 2: Builder +# Stage 3: Builder (memory-optimized) # ----------------------------------------------------------------------------- -FROM mirror.gcr.io/library/node:20-alpine AS builder +FROM base AS builder + +# Reduce memory usage during build +ENV NODE_OPTIONS="--max-old-space-size=512" WORKDIR /app -# Copy dependencies from deps stage +# Copy deps from previous stage COPY --from=deps /app/node_modules ./node_modules -COPY . . -# Build arguments for environment (with sensible default) +# Copy source files (respects .dockerignore) +COPY package.json next.config.* tsconfig.json ./ +COPY public ./public +COPY src ./src + +# Build arguments ARG NEXT_PUBLIC_API_URL=http://localhost:8080 +ARG NEXT_PUBLIC_BACKOFFICE_URL=http://localhost:3001 ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL - -# Build the application +ENV NEXT_PUBLIC_BACKOFFICE_URL=$NEXT_PUBLIC_BACKOFFICE_URL ENV NEXT_TELEMETRY_DISABLED=1 -RUN npm run build + +# Build and cleanup in same layer +RUN pnpm build && \ + rm -rf node_modules/.cache .next/cache # ----------------------------------------------------------------------------- -# Stage 3: Production Runner +# Stage 4: Production Runner (minimal) # ----------------------------------------------------------------------------- FROM mirror.gcr.io/library/node:20-alpine AS runner WORKDIR /app -# Security: Run as non-root user +# Security: non-root user RUN addgroup -g 1001 -S nodejs && \ adduser -u 1001 -S nextjs -G nodejs -# Set production environment ENV NODE_ENV=production \ NEXT_TELEMETRY_DISABLED=1 \ PORT=3000 -# Copy only necessary files for production -COPY --from=builder /app/public ./public -COPY --from=builder /app/.next/standalone ./ -COPY --from=builder /app/.next/static ./.next/static - -# Set ownership to non-root user -RUN chown -R nextjs:nodejs /app +# Copy ONLY standalone output (smallest possible) +COPY --from=builder --chown=nextjs:nodejs /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static USER nextjs