From e4463bfa2f61eed3a81739d497fb16ff07dd39c3 Mon Sep 17 00:00:00 2001 From: Guang Huang Date: Sat, 25 Jan 2025 14:03:42 -0500 Subject: [PATCH] chore(docker): optimize image size using Next.js standalone output - Switch to Next.js standalone output mode - Reduce Docker image size from 1.05GB to 224MB - Decrease compressed image size from 295MB to 74MB - Remove unnecessary dependencies and files from final stage This change significantly improves deployment efficiency and reduces resource usage in production environments. --- Dockerfile | 37 +++++++++++++++++++++++-------------- next.config.js | 1 + 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7fab728..9cbc727 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,33 @@ -FROM node:lts-alpine AS builder - +# Stage 1: Dependencies +FROM node:lts-alpine AS deps RUN apk add --no-cache pnpm - WORKDIR /app COPY package.json pnpm-lock.yaml ./ -RUN pnpm install +# Need all dependencies for build +RUN pnpm install --frozen-lockfile + +# Stage 2: Builder +FROM node:lts-alpine AS builder +RUN apk add --no-cache pnpm +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules COPY . . +# Builds standalone output RUN pnpm build -FROM node:lts-alpine - +# Stage 3: Runner +FROM node:lts-alpine AS runner WORKDIR /app -RUN apk add --no-cache pnpm -COPY package.json pnpm-lock.yaml ./ -RUN pnpm install --prod -COPY --from=builder /app/.next ./.next -COPY --from=builder /app/public ./public -COPY --from=builder /app/next.config.js ./ -ENV PORT 3000 ENV NODE_ENV production +ENV PORT 3000 + +# Only copy standalone output - no need for node_modules +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +USER node EXPOSE 3000 -CMD pnpm start +# Uses standalone server +CMD ["node", "server.js"] diff --git a/next.config.js b/next.config.js index 82fe48b..669e09d 100644 --- a/next.config.js +++ b/next.config.js @@ -4,6 +4,7 @@ const nextConfig = { // The uploader and downloader are both using useEffect to listen for peerjs events // which causes the connection to be created twice. reactStrictMode: false, + output: 'standalone' } module.exports = nextConfig \ No newline at end of file