본문으로 건너뛰기
버전: Next

도커 작업

note

빌드 시간 동안에 도커 컨테이너와 호스트 파일 시스템 간에 참조 링크 또는 하드 링크를 생성하는 것은 불가능합니다. 다음으로 할 수 있는 가장 좋은 방법은 BuildKit 캐시 마운트를 사용하여 빌드 간에 캐시를 공유하는 것입니다. 또는, podman을 사용할 수 있습니다. podman은 빌드 시간에 Btrfs 볼륨을 마운트할 수 있습니다.

도커 이미지 크기 및 빌드 시간 최소화

  • 작은 이미지를 사용하세요 (예: node:XX-slim).
  • 가능하고 합리적인 경우 다중 단계를 활용하세요.
  • BuildKit 캐시 마운트를 활용하세요.

예시 1: 도커 컨테이너에서 번들 빌드

devDependencies는 번들을 빌드하는 데만 필요하기 때문에, pnpm install --prodpnpm installpnpm 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: 모노리포에서 다중 도커 이미지 빌드

App1, app2 및 common이라는 3개의 패키지가 있는 모노레포가 있다고 가정합니다. app1과 app2는 common에 의존하지만 서로는 의존하지 않습니다.

You want to save only necessary dependencies for each package, pnpm deploy should help you with copying only necessary files and packages.

Structure of the monorepo
./
├── 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

Example 3: Build on CI/CD

On CI or CD environments, the BuildKit cache mounts might not be available, because the VM or container is ephemeral and only normal docker cache will work.

So an alternative is to use a typical Dockerfile with layers that are built incrementally, for this scenario, pnpm fetch is the best option, as it only needs the pnpm-lock.yaml file and the layer cache will only be lost when you change the dependencies.

Dockerfile
FROM node:20-slim AS base

ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable

FROM base AS prod

COPY pnpm-lock.yaml /app
WORKDIR /app
RUN pnpm fetch --prod

COPY . /app
RUN pnpm run build

FROM base
COPY --from=prod /app/node_modules /app/node_modules
COPY --from=prod /app/dist /app/dist
EXPOSE 8000
CMD [ "pnpm", "start" ]