使用 Docker
注意
在建置期間,無法在 Docker 容器與主機檔案系統之間建立 reflinks 或 hardlinks。您能做的最佳替代方案是使用 BuildKit 快取掛載在建置之間共用快取。或者,您可以使用 podman,因為它可以在建置期間掛載 Btrfs 磁碟區。
最小化 Docker 映像大小和建置時間
- 使用較小的映像,例如
node:XX-slim
。 - 如果可能且有意義,請利用多階段建置。
- 利用 BuildKit 快取掛載。
範例 1:在 Docker 容器中建置套件
由於 devDependencies
僅在建置套件時需要,因此 pnpm install --prod
會與 pnpm install
和 pnpm run build
分開執行,讓最後一個階段僅複製前一階段中必要的檔案,以將最終映像的大小降至最低。
.dockerignore
node_modules
.git
.gitignore
*.md
dist
Dockerfile
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
COPY . /app
WORKDIR /app
FROM base AS prod-deps
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --prod --frozen-lockfile
FROM base AS build
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run build
FROM base
COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist
EXPOSE 8000
CMD [ "pnpm", "start" ]
範例 2:在單一儲存庫中建置多個 Docker 映像
假設您有一個包含 3 個套件的單一儲存庫:app1、app2 和 common;app1 和 app2 相依於 common,但彼此不相依。
您只想儲存每個套件必要的相依項,pnpm deploy
應該可以協助您僅複製必要的檔案和套件。
單一儲存庫的結構
./
├── Dockerfile
├── .dockerignore
├── .gitignore
├── packages/
│ ├── app1/
│ │ ├── dist/
│ │ ├── package.json
│ │ ├── src/
│ │ └── tsconfig.json
│ ├── app2/
│ │ ├── dist/
│ │ ├── package.json
│ │ ├── src/
│ │ └── tsconfig.json
│ └── common/
│ ├── dist/
│ ├── package.json
│ ├── src/
│ └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
└── tsconfig.json
pnpm-workspace.yaml
packages:
- 'packages/*'
.dockerignore
node_modules
.git
.gitignore
*.md
dist
Dockerfile
FROM node:20-slim AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
FROM base AS build
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
RUN pnpm run -r build
RUN pnpm deploy --filter=app1 --prod /prod/app1
RUN pnpm deploy --filter=app2 --prod /prod/app2
FROM base AS app1
COPY --from=build /prod/app1 /prod/app1
WORKDIR /prod/app1
EXPOSE 8000
CMD [ "pnpm", "start" ]
FROM base AS app2
COPY --from=build /prod/app2 /prod/app2
WORKDIR /prod/app2
EXPOSE 8001
CMD [ "pnpm", "start" ]
執行下列指令,為 app1 和 app2 建置映像
docker build . --target app1 --tag app1:latest
docker build . --target app2 --tag app2:latest