pnpm fetch

lockfile에서 가상 저장소로 패키지를 가져오면 패키지 매니페스트 파일이 무시됩니다.

사용 시나리오#

이 명령은 도커 이미지 빌드를 향상하기 위해 특별히 설계되었습니다.

Node.js 앱용 Dockerfile 작성에 관한 official guide를 읽어보셨을 수도 있습니다. 아직 읽지 않았다면 먼저 읽어보는 것이 좋습니다.

이 가이드에서 pnpm을 사용하여 프로젝트에 최적화된 Dockerfile을 작성하는 방법을 배웁니다.

FROM node:20

WORKDIR /path/to/somewhere

RUN corepack enable pnpm && corepack install -g pnpm@latest-11

# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.mjs ./

# If you patched any package, include patches before install too
COPY patches patches

RUN pnpm install --frozen-lockfile --prod

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "node", "server.js" ]

.npmrc, package.json, pnpm-lock.yaml, pnpm-workspace.yaml, .pnpmfile.mjs에 변경 사항이 없는 한, docker 빌드 캐시는 docker 이미지 빌드 시간의 대부분을 차지하는 RUN pnpm install --frozen-lockfile --prod 레이어까지 계속 유효합니다.

그러나 package.json은 종속성뿐만 아니라 버전 번호, 스크립트, 기타 도구에 대한 임의의 설정도 포함할 수 있기 때문에, 예상보다 훨씬 자주 수정될 수 있습니다.

monorepo 프로젝트를 빌드하는 Dockerfile을 유지 관리하는 것도 어렵습니다. 다음과 같이 보일 수 있습니다.

FROM node:20

WORKDIR /path/to/somewhere

RUN corepack enable pnpm && corepack install -g pnpm@latest-11

# Files required by pnpm install
COPY .npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml .pnpmfile.mjs ./

# If you patched any package, include patches before install too
COPY patches patches

# for each sub-package, we have to add one extra step to copy its manifest
# to the right place, as docker have no way to filter out only package.json with
# single instruction
COPY packages/foo/package.json packages/foo/
COPY packages/bar/package.json packages/bar/

RUN pnpm install --frozen-lockfile --prod

# Bundle app source
COPY . .

EXPOSE 8080
CMD [ "node", "server.js" ]

보시다시피 하위 패키지를 추가하거나 제거할 때 Dockerfile을 업데이트해야 합니다.

pnpm fetch는 lockfile과 설정 파일(pnpm-workspace.yaml)의 정보만 사용하여 가상 스토어에 패키지를 불러오는 기능을 제공함으로써 위의 문제를 완벽하게 해결합니다.

FROM node:20

WORKDIR /path/to/somewhere

RUN corepack enable pnpm && corepack install -g pnpm@latest-11

# 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


COPY . ./
RUN pnpm install -r --offline --prod


EXPOSE 8080
CMD [ "node", "server.js" ]

이는 단순한 프로젝트와 모노레포 프로젝트 모두에서 작동하며, 필요한 모든 패키지가 이미 가상 스토어에 있으므로 --offline은 pnpm이 패키지 레지스트리와 통신하지 않도록 강제합니다.

기존 lockfile이 변경되지 않는 한 빌드 캐시는 해당 레이어까지 유효하므로, RUN pnpm install -r --offline --prod로 많은 시간을 절약할 수 있습니다.

참고

로컬 file: 프로토콜 종속성은 fetch 시점에 사용할 수 없는 디렉터리를 참조할 수 있으므로(예: Docker 빌드에서) pnpm fetch 중에는 건너뜁니다.

옵션#

--dev, -D#

개발 패키지만 가져옵니다.

--prod, -P#

개발 패키지를 가져오지 않습니다.