Dockerfile 參考
Docker 可以透過讀取 Dockerfile 中的指令自動建置映像檔。 Dockerfile 是一個文字文件,其中包含使用者可以在命令列上呼叫以組裝映像檔的所有命令。 本頁面說明您可以在 Dockerfile 中使用的命令。
概觀
Dockerfile 支援以下指令
指令 | 說明 |
---|---|
ADD(新增檔案) | 新增本地或遠端檔案和目錄。 |
ARG(建置參數) | 使用建構時期變數。 |
CMD(預設指令) | 指定預設指令。 |
COPY(複製檔案) | 複製檔案和目錄。 |
ENTRYPOINT(入口點) | 指定預設執行檔。 |
ENV(環境變數) | 設定環境變數。 |
EXPOSE(暴露埠口) | 描述您的應用程式正在監聽的連接埠。 |
FROM(來源映像檔) | 從基礎映像建立新的建構階段。 |
HEALTHCHECK(健康檢查) | 在啟動時檢查容器的健康狀態。 |
LABEL(標籤) | 將中繼資料新增至映像。 |
維護者 | 指定映像的作者。 |
ONBUILD(建置觸發器) | 指定在建構中使用映像時的指示。 |
RUN(執行指令) | 執行建構指令。 |
SHELL(Shell) | 設定映像的預設 shell。 |
STOPSIGNAL(停止訊號) | 指定用於退出容器的系統呼叫信號。 |
USER(使用者) | 設定使用者和群組 ID。 |
VOLUME(儲存空間) | 建立磁碟區掛載。 |
WORKDIR(工作目錄) | 變更工作目錄。 |
格式
以下是 Dockerfile 的格式
# Comment
INSTRUCTION arguments
指令不區分大小寫。但是,慣例是使用大寫字母,以便更容易區分它們與參數。
Docker 會依序執行 Dockerfile 中的指令。Dockerfile 必須以 FROM
指令開頭。這可以在 解析器指令、註解 和全域範圍的 ARG 之後。FROM
指令指定您正在建構的 基礎映像。FROM
只能在一個或多個 ARG
指令之前,這些指令宣告在 Dockerfile 中的 FROM
行中使用的參數。
BuildKit 將以 #
開頭的行視為註解,除非該行是有效的 解析器指令。行中其他任何地方的 #
標記都被視為參數。這允許像以下這樣的陳述式
# Comment
RUN echo 'we are running some # of cool things'
在執行 Dockerfile 指令之前,會先移除註解行。在執行 echo
指令之前,會移除以下範例中的註解。
RUN echo hello \
# comment
world
以下範例是等效的。
RUN echo hello \
world
註解不支援行繼續字元。
注意
關於空格的注意事項
為了向後相容,註解 (
#
) 和指令 (例如RUN
) 前的空格會被忽略,但不建議使用。在這些情況下,前導空格不會被保留,因此以下範例是等效的# this is a comment-line RUN echo hello RUN echo world
# this is a comment-line RUN echo hello RUN echo world
但是,指令參數中的空格不會被忽略。以下範例會列印帶有前導空格的
hello world
,如指定RUN echo "\ hello\ world"
剖析器指令
解析器指令是選擇性的,會影響 Dockerfile 中後續行的處理方式。解析器指令不會將層新增至建構,也不會顯示為建構步驟。解析器指令以特殊類型的註解形式編寫,格式為 # directive=value
。單個指令只能使用一次。
支援以下解析器指令
處理完註解、空行或建構器指令後,BuildKit 不再尋找解析器指令。相反,它會將任何格式化為解析器指令的內容視為註解,並且不會嘗試驗證它是否可能是解析器指令。因此,所有解析器指令都必須位於 Dockerfile 的頂部。
解析器指令鍵(例如 syntax
或 check
)不區分大小寫,但慣例上使用小寫。指令的值區分大小寫,並且必須以指令的適當大小寫編寫。例如,#check=skip=jsonargsrecommended
無效,因為檢查名稱必須使用 Pascal 大小寫,而不是小寫。慣例上,在任何解析器指令之後都包含一個空行。解析器指令不支援行繼續字元。
由於這些規則,以下範例均無效
由於行繼續而無效
# direc \
tive=value
由於出現兩次而無效
# directive=value1
# directive=value2
FROM ImageName
因為它出現在建構器指令之後,所以被視為註解
FROM ImageName
# directive=value
因為它出現在不是解析器指令的註解之後,所以被視為註解
# About my dockerfile
# directive=value
FROM ImageName
以下 unknowndirective
被視為註解,因為它未被識別。已知的 syntax
指令被視為註解,因為它出現在不是解析器指令的註解之後。
# unknowndirective=value
# syntax=value
解析器指令中允許使用非換行空格。因此,以下幾行都被視為相同的
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
語法
使用 syntax
解析器指令來宣告用於建構的 Dockerfile 語法版本。如果未指定,BuildKit 將使用 Dockerfile 前端的捆綁版本。宣告語法版本可讓您自動使用最新的 Dockerfile 版本,而無需升級 BuildKit 或 Docker Engine,甚至可以使用自定義 Dockerfile 實作。
大多數使用者會希望將此解析器指令設定為 docker/dockerfile:1
,這會導致 BuildKit 在建構之前提取 Dockerfile 語法的最新穩定版本。
# syntax=docker/dockerfile:1
有關解析器指令如何運作的更多資訊,請參閱 自定義 Dockerfile 語法。
跳脫字元
# escape=\
或
# escape=`
escape
指令設定用於轉義 Dockerfile 中字元的字元。如果未指定,則預設轉義字元為 \
。
轉義字元用於轉義行中的字元和轉義換行符。這允許 Dockerfile 指令跨越多行。請注意,無論 Dockerfile 中是否包含 escape
解析器指令,都不會在 RUN
指令中執行轉義,除非在行尾。
將轉義字元設定為 `
在 Windows
上尤其有用,其中 \
是目錄路徑分隔符號。`
與 Windows PowerShell 一致。
考慮以下在 Windows 上會以非顯而易見的方式失敗的範例。第二行結尾的第二個 \
會被解譯為換行符的跳脫字元,而不是第一個 \
跳脫的目標。同樣地,第三行結尾的 \
,假設它實際上被作為指令處理,會導致它被視為行繼續符號。這個 Dockerfile 的結果是第二行和第三行被視為單個指令。
FROM microsoft/nanoserver
COPY testfile.txt c:\\
RUN dir c:\
結果為
PS E:\myproject> docker build -t cmd .
Sending build context to Docker daemon 3.072 kB
Step 1/2 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/2 : COPY testfile.txt c:\RUN dir c:
GetFileAttributesEx c:RUN: The system cannot find the file specified.
PS E:\myproject>
上述問題的一個解決方案是使用 /
作為 COPY
指令和 dir
的目標。然而,這種語法充其量只是令人混淆,因為它不符合 Windows 上的路徑自然規則,最壞的情況下,容易出錯,因為並非所有 Windows 命令都支援 /
作為路徑分隔符號。
透過新增 escape
解析器指令,以下 Dockerfile 可以使用 Windows 上檔案路徑的自然平台語義,按預期成功執行。
# escape=`
FROM microsoft/nanoserver
COPY testfile.txt c:\
RUN dir c:\
結果為
PS E:\myproject> docker build -t succeeds --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1/3 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/3 : COPY testfile.txt c:\
---> 96655de338de
Removing intermediate container 4db9acbb1682
Step 3/3 : RUN dir c:\
---> Running in a2c157f842f5
Volume in drive C has no label.
Volume Serial Number is 7E6D-E0F7
Directory of c:\
10/05/2016 05:04 PM 1,894 License.txt
10/05/2016 02:22 PM <DIR> Program Files
10/05/2016 02:14 PM <DIR> Program Files (x86)
10/28/2016 11:18 AM 62 testfile.txt
10/28/2016 11:20 AM <DIR> Users
10/28/2016 11:20 AM <DIR> Windows
2 File(s) 1,956 bytes
4 Dir(s) 21,259,096,064 bytes free
---> 01c7f3bef04f
Removing intermediate container a2c157f842f5
Successfully built 01c7f3bef04f
PS E:\myproject>
檢查
# check=skip=<checks|all>
# check=error=<boolean>
check
指令用於配置如何評估建置檢查。預設情況下,所有檢查都會運行,並且失敗會被視為警告。
您可以使用 #check=skip=<檢查名稱>
來停用特定檢查。要指定多個要略過的檢查,請用逗號分隔它們。
# check=skip=JSONArgsRecommended,StageNameCasing
要停用所有檢查,請使用 #check=skip=all
。
預設情況下,即使出現警告,建置檢查失敗的建置也會以零狀態碼退出。要使建置在出現警告時失敗,請設定 #check=error=true
。
# check=error=true
注意
當使用帶有
error=true
選項的check
指令時,建議將 Dockerfile 語法 固定到特定版本。否則,當未來版本中新增新的檢查時,您的建置可能會開始失敗。
要同時使用 skip
和 error
選項,請使用分號分隔它們。
# check=skip=JSONArgsRecommended;error=true
要查看所有可用的檢查,請參閱 建置檢查參考。請注意,可用的檢查取決於 Dockerfile 語法版本。為了確保您獲得最新的檢查,請使用 syntax
指令將 Dockerfile 語法版本指定為最新的穩定版本。
環境變數替換
環境變數(使用 ENV
陳述式 宣告)也可以在某些指令中用作要由 Dockerfile 解譯的變數。跳脫字元也用於將類似變數的語法原樣包含在陳述式中。
環境變數在 Dockerfile 中使用 $variable_name
或 ${variable_name}
表示。它們的處理方式相同,大括號語法通常用於解決沒有空格的變數名稱問題,例如 ${foo}_bar
。
${variable_name}
語法還支援以下指定的幾個標準 bash
修飾符。
${variable:-word}
表示如果設定了variable
,則結果將是該值。如果未設定variable
,則word
將是結果。${variable:+word}
表示如果設定了variable
,則word
將是結果,否則結果是空字串。
當在 Dockerfile 中使用 # syntax=docker/dockerfile-upstream:master
語法指令時,Dockerfile 語法的預發布版本支援以下變數替換。
${variable#pattern}
從字串開頭開始搜尋,移除variable
中與pattern
最短的匹配項。str=foobarbaz echo ${str#f*b} # arbaz
${variable##pattern}
從字串開頭開始搜尋,移除variable
中與pattern
最長的匹配項。str=foobarbaz echo ${str##f*b} # az
${variable%pattern}
從字串結尾開始向後搜尋,移除variable
中與pattern
最短的匹配項。string=foobarbaz echo ${string%b*} # foobar
${variable%%pattern}
從字串結尾開始向後搜尋,移除variable
中與pattern
最長的匹配項。string=foobarbaz echo ${string%%b*} # foo
${variable/pattern/replacement}
將variable
中pattern
的第一次出現替換為replacement
。string=foobarbaz echo ${string/ba/fo} # fooforbaz
${variable//pattern/replacement}
將variable
中所有出現的pattern
替換為replacement
。string=foobarbaz echo ${string//ba/fo} # fooforfoz
在所有情況下,word
可以是任何字串,包括其他環境變數。
pattern
是一個 glob 模式,其中 ?
匹配任何單個字元,*
匹配任何數量的字元(包括零)。要匹配文字 ?
和 *
,請使用反斜線跳脫:\?
和 \*
。
您可以透過在變數前新增 \
來跳脫整個變數名稱:例如,\$foo
或 \${foo}
將分別轉換為 $foo
和 ${foo}
文字。
範例(已解析的表示形式顯示在 #
之後)
FROM busybox
ENV FOO=/bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux
Dockerfile 中的以下指令支援環境變數:
ADD(新增檔案)
COPY(複製檔案)
ENV(環境變數)
EXPOSE(暴露埠口)
FROM(來源映像檔)
LABEL(標籤)
STOPSIGNAL(停止訊號)
USER(使用者)
VOLUME(儲存空間)
WORKDIR(工作目錄)
ONBUILD
(與上述其中一個支援的指令組合使用時)
您也可以在 RUN
、CMD
和 ENTRYPOINT
指令中使用環境變數,但在這些情況下,變數替換是由命令 shell 處理的,而不是建置器。請注意,使用 exec 形式的指令不會自動調用命令 shell。請參閱 變數替換。
環境變數替換在整個指令中對每個變數使用相同的值。更改變數的值僅在後續指令中生效。請考慮以下範例:
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
def
的值變為hello
。ghi
的值變為bye
。
.dockerignore 檔案
您可以使用 .dockerignore
檔案從建置環境中排除檔案和目錄。如需詳細資訊,請參閱 .dockerignore 檔案