perf(docker): reuse dependency layers and preserve build caches
This commit is contained in:
1 parent
31691c1c7d
commit
2840ef5d9d
4 files changed
+59
-34
No files matched your search
+14
-17
@@ -1,3 +1,4 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
# ==============================================================================
|
||||
# EpicNext-CMS — Docker image (Node 26.8.1, multi-package-manager, Next.js standalone)
|
||||
# ==============================================================================
|
||||
@@ -19,21 +20,19 @@ RUN npm install -g [email protected] yarn
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# First copy only the manifests so dependency layers are cached when using pnpm.
|
||||
# For npm/yarn the full context is copied below before install.
|
||||
COPY package.json pnpm-workspace.yaml .npmrc ./
|
||||
|
||||
# Copy the rest of the source (brings in whichever lockfile your project uses).
|
||||
COPY . .
|
||||
# Lockfiles and installer settings are the only inputs to the dependency layer.
|
||||
# The wildcard supports pnpm-lock.yaml, package-lock.json and yarn.lock.
|
||||
COPY package.json *lock* pnpm-workspace.yaml .npmrc ./
|
||||
|
||||
# --- Detect package manager & install dependencies ---
|
||||
# Priority: pnpm > yarn > npm
|
||||
# Build arg lets the user force a manager; otherwise it is auto-detected.
|
||||
ARG PACKAGE_MANAGER=
|
||||
|
||||
RUN if [ "$PACKAGE_MANAGER" = "pnpm" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f pnpm-lock.yaml ]; }; then \
|
||||
RUN --mount=type=cache,id=epicnext-pnpm,target=/pnpm/store,sharing=locked \
|
||||
if [ "$PACKAGE_MANAGER" = "pnpm" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f pnpm-lock.yaml ]; }; then \
|
||||
echo ">> Using pnpm" && \
|
||||
pnpm install --frozen-lockfile --ignore-scripts; \
|
||||
pnpm install --frozen-lockfile --ignore-scripts --store-dir=/pnpm/store; \
|
||||
elif [ "$PACKAGE_MANAGER" = "yarn" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f yarn.lock ]; }; then \
|
||||
echo ">> Using yarn" && \
|
||||
yarn install --frozen-lockfile --ignore-scripts; \
|
||||
@@ -45,12 +44,16 @@ RUN if [ "$PACKAGE_MANAGER" = "pnpm" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f pn
|
||||
npm install --ignore-scripts; \
|
||||
fi
|
||||
|
||||
# Source changes invalidate compilation, but keep the installed dependencies.
|
||||
COPY . .
|
||||
|
||||
# Build the production bundle.
|
||||
# The .env file is loaded ONLY inside this RUN layer (not persisted as ENV, so no
|
||||
# secrets end up in the image) — Next.js needs NEXT_PUBLIC_* + validated build-time
|
||||
# values (HOTEL_NAME, DATABASE_URL, AUTH_SECRET, ...) at build time.
|
||||
ENV NODE_ENV=production
|
||||
RUN if [ -f .env ]; then set -a && . ./.env && set +a; fi && \
|
||||
RUN --mount=type=cache,id=epicnext-next,target=/app/.next/cache,sharing=locked \
|
||||
if [ -f .env ]; then set -a && . ./.env && set +a; fi && \
|
||||
if [ "$PACKAGE_MANAGER" = "yarn" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f yarn.lock ]; }; then \
|
||||
yarn build; \
|
||||
elif [ "$PACKAGE_MANAGER" = "npm" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f package-lock.json ]; }; then \
|
||||
@@ -59,14 +62,8 @@ RUN if [ -f .env ]; then set -a && . ./.env && set +a; fi && \
|
||||
pnpm build; \
|
||||
fi
|
||||
|
||||
# Prune dev dependencies for the runtime image.
|
||||
RUN if [ "$PACKAGE_MANAGER" = "yarn" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f yarn.lock ]; }; then \
|
||||
yarn install --production --ignore-scripts && rm -rf node_modules/.cache; \
|
||||
elif [ "$PACKAGE_MANAGER" = "npm" ] || { [ -z "$PACKAGE_MANAGER" ] && [ -f package-lock.json ]; }; then \
|
||||
npm prune --production; \
|
||||
else \
|
||||
pnpm prune --prod; \
|
||||
fi
|
||||
# Standalone output already contains the traced runtime dependencies.
|
||||
# Pruning builder/node_modules here would not shrink the final image.
|
||||
|
||||
# --- Runtime stage ---
|
||||
FROM node:26.8.1-bookworm-slim AS runner
|
||||
|
||||
Reference in new issue
Block a user