Skip to content

Dockerfile指令

提醒:Dockerfile 不是 YAML;每個指令多半會建立一層快取層(layer),並依內容決定快取是否命中。

主要指令有底下十七個,Reference中雖然有列出MAINTAINER這個指令,但是文件中也有說它已經deprecated,不建議使用。

速查表

指令 主要用途 影響階段 會產生層
FROM 指定基底映像、開始一個階段 建置時 不直接產層(起始層)
RUN 建置時執行命令(安裝套件、編譯) 建置時
CMD 容器預設啟動命令(可被覆寫) 執行時 ❌(但寫入中繼資料)
ENTRYPOINT 固定入口程式(常與 CMD 搭配) 執行時
COPY 從 build context 複製檔案 建置時
ADD 類似 COPY,另支援 URL 與自動解壓 tar 建置時
WORKDIR 設定後續指令的工作目錄 建置/執行皆影響
ENV 設定環境變數(寫入映像) 執行時(也影響後續建置)
ARG 建置期參數(不寫入映像) 建置時 ❌(值記錄在歷史)
EXPOSE 宣告容器使用的埠(說明用) 執行時
VOLUME 宣告資料卷掛載點 執行時 ✅(中繼資料層)
USER 設定之後指令/容器的使用者 建置/執行皆影響
LABEL 加上映像中繼資料(作者、來源等)
ONBUILD 設定「被當作基底時」才觸發的指令 建置時(下一層子映像觸發) ❌(註冊)
STOPSIGNAL 指定優雅關閉的訊號 執行時
HEALTHCHECK 健康檢查命令 執行時
SHELL 指定 RUN/CMD/ENTRYPOINT 用的 shell 建置/執行 ✅(變更預設 shell)

1) FROM(必備)

  • 作用:指定基底映像;可用 AS 命名階段以做多階段建置。
  • 常見FROM python:3.12-slim AS builderFROM nginx:alpineFROM --platform=linux/amd64 node:20-alpine
  • 要點:第一個 FROM 開啟第一階段;後續 FROM 會開新階段。ARG 若要用在 FROM,需提前宣告。

2) RUN

  • 作用:在建置時執行命令(如安裝套件、編譯)。
  • 兩種寫法

  • Shell form:RUN apt-get update && apt-get install -y curl

  • Exec form:RUN ["bash","-lc","make build"]
  • 快取:指令/輸入一變,該層與後層都會重建。可合併命令並清理快取檔以減少層。
  • BuildKit 進階RUN --mount=type=cache ...--mount=type=secret ... 可加速或安全注入秘密。

3) CMD

  • 作用:容器預設啟動命令(可被 docker run ... <覆寫> 取代)。
  • 寫法:建議 exec formCMD ["python","app.py"]
  • 與 ENTRYPOINT:常搭配用來提供「預設參數」。

4) ENTRYPOINT

  • 作用:設定固定入口程式docker run 追加的字會當作參數傳給它。
  • 範例

ENTRYPOINT ["gunicorn"]
CMD ["app:app","-w","2"]  # 預設參數,可覆寫
* 選擇:要讓使用者整個改掉命令 → 用 CMD;要固定主程式 → 用 ENTRYPOINT

5) COPY

  • 作用:把 build context 中的檔案複製到映像。
  • 用法COPY src/ /app/、支援 --chown=user:group
  • 快取:來源檔案任何變動會使該層失去快取。
  • 最佳實務:先 COPY requirements.txt 再安裝依賴,最後才 COPY . . 帶入原始碼。

6) ADD

  • 作用:像 COPY,但另外支援:

  • ADD http://... 直接下載(不建議;可讀性/快取較差)

  • ADD xxx.tar /dest 自動解壓
  • 規則COPY 就不用 ADD;需要自解壓 tar 才用。

7) WORKDIR

  • 作用:設定後續指令的工作目錄(不存在會自動建立)。
  • 範例WORKDIR /app 之後 RUN/COPY/CMD 等的相對路徑都以此為基準。

8) ENV

  • 作用:設定環境變數(寫入映像,影響後續建置與執行)。
  • 範例ENV PYTHONDONTWRITEBYTECODE=1ENV PATH="/opt/bin:${PATH}"
  • 對比 ARGENV容器執行時可見ARG 只有建置時存在。

9) ARG

  • 作用:建置期參數(用 --build-arg 傳入);不寫進映像執行環境。
  • 範例

ARG NODE_VERSION=20
FROM node:${NODE_VERSION}-alpine
ARG BUILD_MODE
RUN echo "mode=$BUILD_MODE"
* 範圍:在宣告之後才可用;要用在 FROM 內插值,需放 FROM 之前再重宣告一次供後續層使用。

10) EXPOSE

  • 作用:宣告容器服務埠(文件用途);不會真正開放埠。
  • 範例EXPOSE 80;對外須由 -p 主機:容器 或由 orchestrator 設定。

11) VOLUME

  • 作用:宣告資料卷掛載點,提示該目錄有狀態(避免被覆蓋)。
  • 範例VOLUME ["/data"]
  • 注意:建立匿名卷可能讓資料散落;實務上常改用 compose 或 docker run -v 指定。

12) USER

  • 作用:指定後續指令與容器的使用者/群組(強化安全)。
  • 範例USER nonroot:nonroot
  • 注意:換用戶後若需要安裝檔案,請先調整檔案擁有權或切回 root。

13) LABEL

  • 作用:加入中繼資料(作者、原始碼連結、版本等)。
  • 範例(OCI 建議鍵)
LABEL org.opencontainers.image.source="https://github.com/user/repo" \
      org.opencontainers.image.version="1.0.0"

14) ONBUILD

  • 作用:註冊「延遲執行」的指令;只有當此映像被當作 FROM 基底時才觸發。
  • 用途:做樣板基底(例如自動 COPY/RUN)。
  • 提醒:可能出現「驚喜副作用」,近年較少用。

15) STOPSIGNAL

  • 作用:指定 Docker 要送給主程序的關閉訊號(優雅退出)。
  • 範例STOPSIGNAL SIGTERM 或數字值。

16) HEALTHCHECK

  • 作用:由引擎週期性檢查容器健康狀態。
  • 範例
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
  CMD curl -f http://localhost:8080/health || exit 1
  • 停用HEALTHCHECK NONE

17) SHELL

  • 作用:變更之後 RUN/CMD/ENTRYPOINT 預設使用的 shell。
  • 範例:Linux 預設 /bin/sh -c;需要 bash 時可: SHELL ["bash","-lc"] Windows 影像常用 ["powershell","-Command"]

補充:常見語法與最佳實務

  • JSON(exec)vs Shell formCMD ["node","app.js"](推薦,訊號傳遞正確) vs CMD node app.js
  • 多階段(Multi-stage)FROM ... AS builderCOPY --from=builder ...,縮小最終映像。
  • .dockerignore:務必忽略 .git/node_modules/__pycache__/.env 等,減少洩密與加速建置。
  • 少用 ADD URL:改用 curl/wget + 校驗,更清晰可控。
  • 先依賴、後原始碼:讓安裝依賴層可被快取。
  • 非 root 執行USER 切換,降低風險。
  • EXPOSE 不是開埠:實際對外要 -p 或由 orchestrator 配置。

Note

快速拆解 Docker 映像名稱語法:

[REGISTRY_HOST[:PORT]/][NAMESPACE/]<REPOSITORY>[:TAG][@DIGEST]

套用到你的例子:

  • pythonREPOSITORY(映像檔名稱)
  • 3.12-slimTAG(標籤/版本變體)

一些對照例子:

  • python:3.12-slim = docker.io/library/python:3.12-slim官方映像library/ 命名空間隱含)

  • myuser/myapp:1.0

    • myuserNAMESPACE(帳號或組織)
    • myapp → REPOSITORY
    • 1.0 → TAG
  • ghcr.io/acme/api:prod

    • ghcr.io → REGISTRY(GitHub Container Registry)
    • acme → NAMESPACE
    • api → REPOSITORY
    • prod → TAG

補充:

  • 如果沒寫 :TAG,預設是 :latest(不建議在生產用,最好明確標版本)。
  • @sha256:...DIGEST,用來鎖定「內容不可變」的精確版本。
  • 這裡的名稱跟「容器內的 Linux 使用者」或 --user 無關。

參考資料