diff --git a/docs/cli/fetch.md b/docs/cli/fetch.md index ee49648f132f..fbb0c7f40032 100644 --- a/docs/cli/fetch.md +++ b/docs/cli/fetch.md @@ -12,23 +12,28 @@ This command is specifically designed to improve building a docker image. You may have read the [official guide] to writing a Dockerfile for a Node.js app, if you haven't read it yet, you may want to read it first. +Also see [Working wirh Docker](../docker.md), for examples of multi-stage +builds, and `pnpm deploy` that can be combined with this command for a smaller +final image. + From that guide, we learn to write an optimized Dockerfile for projects using pnpm, which looks like ```Dockerfile FROM node:20 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm && corepack install -g pnpm@latest-10 WORKDIR /path/to/somewhere -RUN corepack enable pnpm && corepack install -g pnpm@latest-10 - # Files required by pnpm install COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./ # If you patched any package, include patches before install too COPY patches patches -RUN pnpm install --frozen-lockfile --prod +RUN pnpm --mount=type=cache,id=pnpm,target=/pnpm/store install --frozen-lockfile --prod # Bundle app source COPY . . @@ -52,11 +57,12 @@ look like ```Dockerfile FROM node:20 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm && corepack install -g pnpm@latest-10 WORKDIR /path/to/somewhere -RUN corepack enable pnpm && corepack install -g pnpm@latest-10 - # Files required by pnpm install COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.cjs ./ @@ -69,7 +75,7 @@ COPY patches patches COPY packages/foo/package.json packages/foo/ COPY packages/bar/package.json packages/bar/ -RUN pnpm install --frozen-lockfile --prod +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile --prod # Bundle app source COPY . . @@ -86,18 +92,19 @@ to load packages into the virtual store using only information from a lockfile a ```Dockerfile FROM node:20 +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable pnpm && corepack install -g pnpm@latest-10 WORKDIR /path/to/somewhere -RUN corepack enable pnpm && corepack install -g pnpm@latest-10 - # pnpm fetch does require only lockfile COPY pnpm-lock.yaml pnpm-workspace.yaml ./ # If you patched any package, include patches before running pnpm fetch COPY patches patches -RUN pnpm fetch --prod +RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm fetch --prod ADD . ./ diff --git a/docs/docker.md b/docs/docker.md index 3f71152167ae..7bead2db2bae 100644 --- a/docs/docker.md +++ b/docs/docker.md @@ -3,6 +3,8 @@ id: docker title: Working with Docker --- +Also see [pnpm fetch](./cli/fetch.md) for a command that can be used to speed up consecutive builds. + :::note It is impossible to create reflinks or hardlinks between a Docker container and the host filesystem during build time. @@ -165,3 +167,54 @@ COPY --from=prod /app/dist /app/dist EXPOSE 8000 CMD [ "pnpm", "start" ] ``` + +### Example 4: All techniques in one + +A verstaile option is to just use both fetch, deploy, cache mounts, newer Docker +features like `--link` all in one Docker file, and benefit from the build +performance and image size reducation at the cost of a more complex Dockerfile. + +This also includes running as a normal user instead of root, and properly +caching pnpm with corepack so the image won't need to download it on startup. + +```dockerfile title="Dockerfile" +# syntax=docker/dockerfile:1 +FROM node:22 AS build +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV COREPACK_HOME="/corepack" +# Package to be built and deployed from the workspace +ARG PACKAGE=example + +WORKDIR /workspace +# The package.json is for corepack, pnpm fetch needs only the lockfile and workspace configuration +COPY --link package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +# If you have patches: +# COPY --link patches patches +RUN corepack enable && corepack install +RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ + pnpm fetch + +COPY --link . . + +RUN pnpm install --offline --frozen-lockfile + +RUN pnpm --filter $PACKAGE... build + +RUN --mount=type=cache,id=pnpm,target=/pnpm/store \ + pnpm --filter $PACKAGE deploy --prod deploy + +FROM node:22-slim AS runtime +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +ENV COREPACK_HOME="/corepack" + +WORKDIR /app +COPY --link --from=build /workspace/deploy . + +RUN corepack enable && corepack install +ENV COREPACK_DEFAULT_TO_LATEST=0 COREPACK_ENABLE_NETWORK=0 + +USER 1000 +CMD ["pnpm", "--silent", "start"] +```