READ-ONLY PACKAGE PREVIEW

docker-build-strategies/assets/Dockerfile.nodejs

Version 3e1cbd179989 · Apache-2.0. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.

← Return to resource and package checksum

# syntax=docker/dockerfile:1

# --- Production dependencies ---
FROM node:22-alpine AS deps
WORKDIR /src
# package.json/package-lock.json are bind-mounted (not COPY-ed): npm ci never
# rewrites them, so they never need to enter a layer.
# Registry credentials, if any, are mounted only for the duration of `npm ci`.
# `required=false` keeps the build green when no .npmrc is provided.
# Invoke with: docker buildx build --secret id=npmrc,src=$HOME/.npmrc .
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=secret,id=npmrc,target=/root/.npmrc,required=false \
    --mount=type=cache,target=/root/.npm \
    npm ci --omit=dev

# --- Build stage ---
FROM node:22-alpine AS build
WORKDIR /src
RUN --mount=type=bind,source=package.json,target=package.json \
    --mount=type=bind,source=package-lock.json,target=package-lock.json \
    --mount=type=secret,id=npmrc,target=/root/.npmrc,required=false \
    --mount=type=cache,target=/root/.npm \
    npm ci
COPY . .
RUN npm run build

# --- Runtime stage ---
FROM node:22-alpine AS runtime
WORKDIR /app

RUN addgroup --system --gid 1001 appgroup && \
    adduser --system --uid 1001 --ingroup appgroup appuser

# Production node_modules from deps stage, built output from build stage
COPY --from=deps --chown=appuser:appgroup /src/node_modules ./node_modules
COPY --from=build --chown=appuser:appgroup /src/dist ./dist
COPY --from=build --chown=appuser:appgroup /src/package.json .

USER appuser
EXPOSE 3000

LABEL org.opencontainers.image.source="<source-repository-url>"

ENTRYPOINT ["node", "dist/index.js"]