refactor(docker): update Dockerfile for Next.js 15 and improve environment variable handling

This commit is contained in:
hamed
2026-06-25 20:59:33 +03:30
parent 09373c46d6
commit ac15552cc1
2 changed files with 65 additions and 33 deletions
+4 -4
View File
@@ -14,10 +14,10 @@ build
coverage coverage
.nyc_output .nyc_output
# Environment files # Environment files — never bake secrets into the image; pass via build args / runtime env
.env*.local .env
.env.development .env.*
.env.test !.env.example
# IDE # IDE
.vscode .vscode
+60 -28
View File
@@ -1,48 +1,80 @@
# Dockerfile for Next.js 14 - Optimized for Production # syntax=docker/dockerfile:1
# Multi-stage Dockerfile for Next.js 15 (App Router, output: 'standalone')
# Based on the official Next.js Docker example, tuned for Coolify.
# Reference: https://github.com/vercel/next.js/blob/canary/examples/with-docker/Dockerfile
# Use the official Node.js image with Alpine Linux for a smaller footprint # ----------------------------------------------------------------------------
# Base image
# ----------------------------------------------------------------------------
FROM node:22-alpine AS base FROM node:22-alpine AS base
# libc6-compat is recommended by the Next.js image for some native deps (sharp, etc.)
# Set the working directory in the container RUN apk add --no-cache libc6-compat
WORKDIR /app WORKDIR /app
# Copy package.json and package-lock.json (or yarn.lock) # ----------------------------------------------------------------------------
COPY package*.json ./ # 1. Dependencies — installed in a dedicated layer so they are cached as long
# as package.json / lockfile / .npmrc do not change.
# ----------------------------------------------------------------------------
FROM base AS deps
COPY package.json package-lock.json .npmrc ./
# Reproducible install honouring the lockfile (.npmrc provides legacy-peer-deps).
RUN npm ci
# Install dependencies - leveraging Docker cache # ----------------------------------------------------------------------------
RUN npm i --force # 2. Builder — produces the standalone output.
# NEXT_PUBLIC_* values are inlined into the client bundle at BUILD time,
# so they must be passed as build args. DEV_MODE is read in app/layout.js
# to enable Google Analytics, so it must also be present at build time.
# ----------------------------------------------------------------------------
FROM base AS builder
WORKDIR /app
# Copy the rest of the application code # Build-time arguments (Coolify: set these as Build Variables)
ARG NEXT_PUBLIC_API_URL
ARG NEXT_PUBLIC_CLIENT_ID
ARG NEXT_PUBLIC_CLIENT_SECRET
ARG DEV_MODE=FALSE
# Expose them to `next build`
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
ENV NEXT_PUBLIC_CLIENT_ID=$NEXT_PUBLIC_CLIENT_ID
ENV NEXT_PUBLIC_CLIENT_SECRET=$NEXT_PUBLIC_CLIENT_SECRET
ENV DEV_MODE=$DEV_MODE
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
# Build the Next.js application
RUN npm run build RUN npm run build
# Stage 2: Production image - smaller and leaner # ----------------------------------------------------------------------------
FROM node:22-alpine AS runner # 3. Runner — minimal production image running the standalone server.
# ----------------------------------------------------------------------------
# Set the working directory FROM base AS runner
WORKDIR /app WORKDIR /app
# Set environment variables ENV NODE_ENV=production
ENV NODE_ENV $NODE_ENV ENV NEXT_TELEMETRY_DISABLED=1
ENV NEXT_TELEMETRY_DISABLED 1 # The standalone server must bind to all interfaces inside the container.
ENV HOSTNAME=0.0.0.0
ENV PORT=3000
# Add a non-root user for security # Run as a non-root user for security.
RUN addgroup -g 1001 -S nodejs RUN addgroup --system --gid 1001 nodejs \
RUN adduser -S nextjs -u 1001 && adduser --system --uid 1001 nextjs
# Copy only the necessary files from the builder stage # Public assets (served by the standalone server).
COPY --from=base /app/next.config.js ./ COPY --from=builder /app/public ./public
COPY --from=base /app/public ./public
COPY --from=base --chown=nextjs:nodejs /app/.next/standalone ./ # Standalone output already contains a minimal node_modules + server.js.
COPY --from=base --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
# Static assets are NOT included in standalone and must be copied separately.
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Change ownership of all copied files to the non-root user
USER nextjs USER nextjs
# Expose the port Next.js listens on
EXPOSE 3000 EXPOSE 3000
# Command to start the Next.js server in production mode # server.js is generated by Next.js at the root of the standalone output.
CMD ["node", "server.js"] CMD ["node", "server.js"]