1- # ======================
2- # Base
3- # ======================
1+ # Base Node.js image
42FROM node:20-alpine AS base
5- WORKDIR /app
6- RUN apk add --no-cache libc6-compat
73
84# ======================
9- # Dependencies
5+ # Set build arguments for COS credentials
106# ======================
7+ ENV COS_SECRET_ID=$COS_SECRET_ID
8+ ENV COS_SECRET_KEY=$COS_SECRET_KEY
9+ ENV COS_BUCKET=$COS_BUCKET
10+ ENV COS_REGION=$COS_REGION
11+
12+ # Install dependencies only when needed
1113FROM base AS deps
1214
15+ WORKDIR /app
16+
17+ RUN apk add --no-cache ca-certificates curl
18+
1319RUN corepack enable && corepack prepare pnpm@latest --activate
1420
15- COPY package.json pnpm-lock.yaml ./
21+ # Copy package files
22+ COPY package.json pnpm-lock.yaml* ./
1623
1724RUN pnpm install --frozen-lockfile
1825
19- # ======================
20- # Builder
21- # ======================
26+ # Rebuild the source code only when needed
2227FROM base AS builder
2328WORKDIR /app
2429
30+ # Copy node_modules from deps
2531COPY --from=deps /app/node_modules ./node_modules
32+
33+ # Copy all project files
2634COPY . .
2735
36+ # Set Next.js telemetry to disabled
2837ENV NEXT_TELEMETRY_DISABLED=1
2938
39+ # Copy production environment variables for build
40+ COPY .env.production .env.production
41+
42+ # Build the application
3043RUN npm run build
3144
32- # 确保 standalone 存在
33- RUN test -d .next/standalone
45+ # Verify standalone build was created
46+ RUN ls -la .next/ && \
47+ if [ ! -d ".next/standalone" ]; then \
48+ echo "ERROR: .next/standalone directory not found. Make sure output: 'standalone' is set in next.config.ts" ; \
49+ exit 1; \
50+ fi
51+
52+ RUN wget https://cosbrowser.cloud.tencent.com/software/coscli/coscli-linux-amd64 -O /usr/local/bin/coscli && \
53+ chmod +x /usr/local/bin/coscli && \
54+ coscli --version
3455
3556# ======================
36- # Runtime
57+ # Upload static files to COS
3758# ======================
38- FROM node:20-alpine AS runner
59+ RUN coscli sync .next/static cos://${COS_BUCKET}/next-static/ \
60+ --region $COS_REGION --force && \
61+ coscli sync public cos://${COS_BUCKET}/public/ \
62+ --region $COS_REGION --force
63+
64+ # Production image, copy all the files and run next
65+ FROM base AS runner
3966WORKDIR /app
4067
68+ # Set environment variables
4169ENV NODE_ENV=production
4270ENV NEXT_TELEMETRY_DISABLED=1
4371
72+ # Create a non-root user
4473RUN addgroup --system --gid 1001 nodejs && \
4574 adduser --system --uid 1001 nextjs
4675
76+ # Copy public assets
77+ COPY --from=builder /app/public ./public
78+
79+ # Copy standalone application
4780COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
81+
82+ # Copy static assets
4883COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
49- COPY --from=builder --chown=nextjs:nodejs /app/public ./public
5084
85+ # Switch to non-root user
5186USER nextjs
5287
88+ # Expose application port
5389EXPOSE 3000
90+
91+ # Set environment variable for port
5492ENV PORT=3000
5593ENV HOSTNAME=0.0.0.0
5694
95+ # Health check to verify container is running properly
96+ HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
97+ CMD wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1
98+
99+ # Start the application
57100CMD ["node" , "server.js" ]
0 commit comments