package update
This commit is contained in:
76
DockerFile
76
DockerFile
@ -1,55 +1,69 @@
|
|||||||
# Stage 1: Build
|
# Multi-stage build for Next.js frontend
|
||||||
# Change from node:18-alpine to node:22-alpine
|
FROM node:22 AS base
|
||||||
FROM node:22-alpine AS builder
|
|
||||||
|
|
||||||
|
# Install dependencies only when needed
|
||||||
|
FROM base AS deps
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Build arguments - MUST be before COPY to be available during build
|
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
|
||||||
ARG NEXT_PUBLIC_API_URL
|
RUN \
|
||||||
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
|
||||||
|
elif [ -f package-lock.json ]; then npm ci; \
|
||||||
|
elif [ -f pnpm-lock.yaml ]; then corepack enable && pnpm i --frozen-lockfile; \
|
||||||
|
else echo "Lockfile not found." && exit 1; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Copy package files
|
# Rebuild the source code only when needed
|
||||||
COPY package.json package-lock.json ./
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
# Install ALL dependencies (including dev dependencies for build)
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
RUN npm ci
|
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Build the app
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
|
ARG NEXT_PUBLIC_API_URL
|
||||||
|
ARG NODE_ENV=production
|
||||||
|
|
||||||
|
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||||
|
ENV NODE_ENV=${NODE_ENV}
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Stage 2: Run
|
# Production image
|
||||||
# Change from node:18-alpine to node:22-alpine
|
FROM base AS runner
|
||||||
FROM node:22-alpine AS runner
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Set to production
|
|
||||||
ENV NODE_ENV=production
|
|
||||||
|
|
||||||
# Runtime environment variable
|
|
||||||
ARG NEXT_PUBLIC_API_URL
|
ARG NEXT_PUBLIC_API_URL
|
||||||
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
ENV NEXT_PUBLIC_API_URL=${NEXT_PUBLIC_API_URL}
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Copy necessary files from the standalone build
|
# Create non-root user
|
||||||
|
RUN addgroup --system --gid 1001 nodejs && \
|
||||||
|
adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
# Copy public folder
|
||||||
COPY --from=builder /app/public ./public
|
COPY --from=builder /app/public ./public
|
||||||
COPY --from=builder /app/.next/standalone ./
|
|
||||||
COPY --from=builder /app/.next/static ./.next/static
|
|
||||||
|
|
||||||
# Create cache directory with proper permissions
|
# Set correct permissions for prerender cache
|
||||||
RUN mkdir -p .next/cache/images && \
|
RUN mkdir .next && chown nextjs:nodejs .next
|
||||||
chmod -R 777 .next/cache
|
|
||||||
|
# Leverage output traces to reduce image size
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
# Copy healthcheck script
|
||||||
|
COPY --chown=nextjs:nodejs healthcheck.js .
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
# Expose port
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
# Set node options to fix the IPv6 issue we discussed earlier
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
|
||||||
ENV NODE_OPTIONS="--dns-result-order=ipv4first"
|
CMD node healthcheck.js || exit 1
|
||||||
|
|
||||||
# Start the app
|
|
||||||
CMD ["node", "server.js"]
|
CMD ["node", "server.js"]
|
||||||
18
healthcheck.js
Normal file
18
healthcheck.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// healthcheck.js
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
host: 'localhost',
|
||||||
|
port: process.env.PORT || 3000,
|
||||||
|
path: '/',
|
||||||
|
timeout: 5000,
|
||||||
|
};
|
||||||
|
|
||||||
|
const req = http.request(options, (res) => {
|
||||||
|
process.exit(res.statusCode === 200 ? 0 : 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
req.on('error', () => process.exit(1));
|
||||||
|
req.on('timeout', () => process.exit(1));
|
||||||
|
|
||||||
|
req.end();
|
||||||
Reference in New Issue
Block a user