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 builder、FROM nginx:alpine、FROM --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 form:
CMD ["python","app.py"]。 - 與 ENTRYPOINT:常搭配用來提供「預設參數」。
4) ENTRYPOINT
- 作用:設定固定入口程式;
docker run追加的字會當作參數傳給它。 - 範例:
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=1、ENV PATH="/opt/bin:${PATH}" - 對比
ARG:ENV在容器執行時可見;ARG只有建置時存在。
9) ARG
- 作用:建置期參數(用
--build-arg傳入);不寫進映像執行環境。 - 範例:
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 form:
CMD ["node","app.js"](推薦,訊號傳遞正確) vsCMD node app.js。 - 多階段(Multi-stage):
FROM ... AS builder→COPY --from=builder ...,縮小最終映像。 .dockerignore:務必忽略.git/、node_modules/、__pycache__/、.env等,減少洩密與加速建置。- 少用
ADD URL:改用curl/wget+ 校驗,更清晰可控。 - 先依賴、後原始碼:讓安裝依賴層可被快取。
- 非 root 執行:
USER切換,降低風險。 EXPOSE不是開埠:實際對外要-p或由 orchestrator 配置。
Note
快速拆解 Docker 映像名稱語法:
套用到你的例子:
python→ REPOSITORY(映像檔名稱)3.12-slim→ TAG(標籤/版本變體)
一些對照例子:
-
python:3.12-slim=docker.io/library/python:3.12-slim(官方映像,library/命名空間隱含) -
myuser/myapp:1.0myuser→ NAMESPACE(帳號或組織)myapp→ REPOSITORY1.0→ TAG
-
ghcr.io/acme/api:prodghcr.io→ REGISTRY(GitHub Container Registry)acme→ NAMESPACEapi→ REPOSITORYprod→ TAG
補充:
- 如果沒寫
:TAG,預設是:latest(不建議在生產用,最好明確標版本)。 @sha256:...是 DIGEST,用來鎖定「內容不可變」的精確版本。- 這裡的名稱跟「容器內的 Linux 使用者」或
--user無關。