From fe299cac64024f14a512204ea51cdc8aa0c94e22 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 30 Jun 2026 12:42:11 +0800 Subject: [PATCH] =?UTF-8?q?refactor(Dockerfile):=20=E6=94=B9=E7=82=BA?= =?UTF-8?q?=E6=9C=80=E6=96=B0=20node=20=E5=A4=9A=E9=9A=8E=E6=AE=B5?= =?UTF-8?q?=E5=BB=BA=E7=BD=AE=E4=BB=A5=E7=B8=AE=E5=B0=8F=E6=9C=80=E7=B5=82?= =?UTF-8?q?=E6=98=A0=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5057987..7c596d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,24 +1,42 @@ +# syntax=docker/dockerfile:1 # ============================================================================= # 用途: 建置 calculate-version Action 的容器映像。 -# 以 Node.js 執行環境打包 /app 下的 Node.js 程式 (專案已從 bash 改寫為 Node.js), -# 並安裝 bash 以執行 entrypoint.sh,再由其啟動 Node.js 程式。 -# 更新日期: 2026/06/26 10:28:36 +# 採多階段建置:build 階段以最新 node 準備主程式 (/app) 與進入點腳本, +# runtime 階段改用 node slim 基底縮小最終映像,再由 entrypoint.sh 啟動 Node.js 主程式。 +# 更新日期: 2026/06/30 12:12:52 # ============================================================================= -# 基底映像:Node.js LTS 的 Alpine 版本 (體積小)。 -FROM node:lts-alpine +# 1. 參數處理:node 版本以 ARG 注入。預設使用最新版 (build: node:latest / runtime: node:slim); +# 可於建置時以 --build-arg NODE_VERSION=22 --build-arg NODE_RUNTIME=22-slim 覆寫。 +# 注意:最新版 slim 一律為 node:slim,無 node:latest-slim 這個 tag,故以獨立 NODE_RUNTIME 帶入。 +ARG NODE_VERSION=latest +ARG NODE_RUNTIME=slim -# entrypoint.sh 以 bash 撰寫,Alpine 預設無 bash 需另行安裝 -# --no-cache 不保留 apk 索引快取以縮小映像(保留 TLS 憑證檢查以防中間人攻擊)。 -RUN apk add --no-cache bash +# ---- build 階段:安裝相依、準備主程式與進入點 ---- +FROM node:${NODE_VERSION} AS build +WORKDIR /build -# 複製容器進入點腳本至根目錄。 -COPY entrypoint.sh /entrypoint.sh -# 複製整個 app 目錄 (Node.js 程式) 至 /app。 -COPY app/ /app/ +# 2. 安裝套件:先單獨複製相依描述以利 layer 快取,再安裝 production 相依。 +# 本專案目前無外部相依;有 package.json 時仍嘗試安裝 (有 lockfile 用 npm ci,否則 npm install), +# 無相依時為 no-op,但保留此步可在未來新增相依時自動生效。 +COPY app/package*.json ./app/ +RUN if [ -f ./app/package.json ]; then \ + cd ./app && (npm ci --omit=dev || npm install --omit=dev); \ + fi -# 賦予進入點腳本可執行權限,否則 ENTRYPOINT 無法執行。 -RUN chmod +x /entrypoint.sh +# 3. 複製檔案:複製主程式 (app/) 與容器進入點腳本。 +COPY app/ ./app/ +COPY entrypoint.sh ./entrypoint.sh -# 設定容器啟動時執行的進入點 (內部會 exec node /app/index.js "$@")。 +# 4. 執行程序:賦予進入點腳本可執行權限。本專案為純 JS,無需 build/transpile,故此步僅設定權限。 +RUN chmod +x ./entrypoint.sh + +# ---- runtime 階段:以 slim 基底縮小最終映像 ---- +# 5. 縮小映像檔:多階段建置,runtime 僅自 build 階段帶入執行真正需要的檔案 (app/ 與 entrypoint.sh), +# 不含 build 階段的快取。node slim 為 Debian 基底,內建 bash,足以執行 entrypoint.sh。 +FROM node:${NODE_RUNTIME} AS runtime +COPY --from=build /build/app /app +COPY --from=build /build/entrypoint.sh /entrypoint.sh + +# 6. 設定入口:以 entrypoint.sh 為容器進入點 (其內以 exec node /app/index.js "$@" 啟動主程式)。 ENTRYPOINT ["/entrypoint.sh"]