背景問題

目前公司內部的 Node.js 後端專案使用 Docker 部署,但現有的建置方式存在以下問題:

  1. yarn install 未善用快取機制,時間可能高達 4 分鐘
  2. 未利用 Docker layer cache,每次 docker push/pull 需傳輸約 300 MB 的資料,影響部署效率
  3. 映像檔包含 devDependencies,導致額外的體積與不必要的依賴

建置環境

GitLab CI,Runner 使用 shell executor。

改善方式

  1. 優化 Docker layer cache
  1. 利用 Docker cache mounts
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \\
  yarn install --production --frozen-lockfile
  1. 利用 multi-stage build。先用一個 builder 安裝依賴和編譯,最後再把需要的檔案複製進 app image。如此一來 app image 不會包含 devDependency。減少映像檔大小。

Dockerfile

以下是優化後的 Dockerfile

FROM node:20 AS builder
WORKDIR /app
COPY package.json yarn.lock ./
RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \\
  yarn install --production --frozen-lockfile && \\
  mv node_modules prod_node_modules && \\
  yarn install --frozen-lockfile
COPY . .
RUN yarn build

FROM node:20 AS app
WORKDIR app
COPY package.json .
COPY --from=builder /app/prod_node_modules ./node_modules
COPY --from=builder /app/dist ./dist
ENTRYPOINT ["node", "--enable-source-maps", "dist/main.js"]

GitLab CI 配置