純乾貨!Dockerfile 常用指令清單
Dockerfile 常用指令
一、Dockerfile
Docker 可以通過Dockerfile
自動構建鏡像,Dockerfile
是一個包含多個指令的文檔。如下
# syntax=docker/dockerfile:1
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
二、FROM
FROM
命令用於初始化一個新的構建階段,併爲後續指令設置基礎鏡像:
FROM [--platform=<platform>] <image> [AS <name>]
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
-
FROM
指令用於指定基礎鏡像,ARG
是唯一可以位於FROM
指令之前的指令,一般用於聲明基礎鏡像的版本。 -
單個
Dockerfile
可以多次出現FROM
,以使用之前的構建階段作爲另一個構建階段的依賴項。 -
--platform
選項可用在FROM
多平臺鏡像的情況下指定平臺。例如,linux/amd64、lunux/arm64、windows/amd64。 -
AS name
表示爲構建階段命令,在後續FROM
和COPY --from=name
說明中可以使用這個名詞,引用此階段構建的映像。 -
tag
或digest
值是可選的。如果您省略其中任何一個,構建器默認使用latest
標籤。如果找不到指定tag
,構建起將返回錯誤。
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
三、RUN
RUN
指令將在當前鏡像之上的新層中執行命令,並且提交結果。在docker build
時運行。
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
RUN 有兩種形式:
-
RUN :shell 形式,命令在 shell 中運行,默認在 Linux 上使用
/bin/sh -c
,在 Windows 上使用cmd /S /C
。 -
RUN ["程序名","param1","param1"]:exec 形式,不會觸發 shell,所以 $HOME 這樣的環境變量無法使用,但它可以在沒有 bash 的鏡像中執行。
說明:
-
可以使用反斜槓(\)將單個
RUN
命令延續到下一行。 -
RUN
在下一次構建期間,指令緩存不會自動失效。可以使用--no-cache
選項使指令緩存失效。如 RUN apt-get update 之類的構建緩存將在下一次構建期間被重用,此時構建中可能安裝過時版本的工具,但我們可以使用 --no-cache 標誌來使 RUN 命令的緩存失效,如 docker build --no-cache。 -
Dockerfile 的指令每執行一次就會給鏡像新建一層只讀層。過多無意義的層會造成鏡像膨脹過大,可以使用 && 符號連接多個命令,這樣執行 RUN 指令後之後創建一層鏡像。
有些命令會使用管道(|),如:
RUN wget -O - https://some.site | wc -l > /number
Docker 使用/bin/sh -c
解釋器,解釋器只計算所有一個命令的退出狀態碼以確定命令是否執行成功,如上例,只要wc -l
執行成功,即使wget
命令失敗,這個構建步驟也會生成一層新鏡像。如果希望命令由於管道中任意階段命令的錯誤而失敗,需要預先設置set-o pipefail&&
,如下:
RUN set -o pipefail && wget -O - https://some.site | wc -l > /number
注意,基於 debian 的鏡像要使用 exec 形式支持
-o pipefail
:RUN ["/bin/bash", "-c", "set -o pipefail && wget -O - https://some.site | wc -l > /number"]
四、CMD
Dockerfile 使用RUN
指令完成docker build
所有的環境安裝與配置,通過CMD
指令來指示docker run
命令運行鏡像時要執行的命令。Dockerfile 只允許使用一次CMD
命令。使用多個CMD
會抵消之前所有的命令,只有最後一個命令生效。一般來說,這是整個 Dockerfile 腳本的最後一個命令。
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
CMD 有三種形式:
-
CMD ["exec","param1","param2"]:使用 exec 執行,推薦方式。
-
CMD command param1 param2:在 / bin/sh 中執行,可以提供交互操作。
-
CMD ["param1","param2"]:提供給 ENTRYPOINT 的默認參數(極少這樣使用)。
五、EXPOSE
EXPOSE
指令通知容器在運行時監聽某個端口,可以指定 TCP 或 UDP,如果不指定協議,默認爲 TCP 端口。但是爲了安全,docker run
命令如果沒有帶上相應的端口映射參數,Docker 並不會將端口映射出去。
EXPOSE 80/tcp
EXPOSE 80/udp
指定映射端口方式:
docker run -P:將所有端口發佈到主機接口,每個公開端口綁定到主機上的隨機端口,端口範圍在/proc/sys/net/ipv4/ip_local_port_range
定義的臨時端口範圍內。
docker run -p :顯式映射單個端口或端口範圍。
六、LABEL
LABEL
指令爲鏡像添加標籤,當前鏡像會繼承父鏡像的標籤,如果與父標籤重複,會覆蓋之前的標籤。
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
或
LABEL multi.label1="value1" multi.label2="value2" other="value3"
可以使用如下方式查看鏡像標籤:
docker image inspect --format='' myimage
查看結果實例:
{
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
}
七、ENV
ENV
命令用來在執行docker run
命令運行鏡像時指定自動設置的環境變量。這個環境變量可以在後續任何 RUN 命令中使用,並在容器運行時保持。一般用於軟件更便捷的運行,如:
ENV PATH=/usr/local/nginx/bin:$PATH
CMD ["nginx"]
設置的環境變量將持續存在,可以使用docker inspect
來查看。這些環境變量可以通過docker run --env <key>=<value>
命令的參數來修改。
八、ARG
ARG 命令定義用戶只在構建時使用的變量,效果和docker build --build-arg <varname>=<value>
一樣,這個參數只會在構建時存在,不會保留在鏡像中。
ARG <name>[=<default value>]
ARG 與 ENV 類似,不同的是 ENV 會在鏡像構建結束後一直保存在容器中,而 ARG 會在鏡像構建結束狗消失。一般運用在希望整個構建過程是無交互的,那麼可以使用 ARG 命令(僅限 Debian 發行版)。
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y ...
Docker 有一組預定義的 ARG 變量,您可以在 Dockerfile 中沒有相應指令的情況下使用這些變量。
-
HTTP_PROXY
-
http_proxy
-
HTTPS_PROXY
-
https_proxy
-
FTP_PROXY
-
ftp_proxy
-
NO_PROXY
-
no_proxy
要使用這些,請使用 --build-arg 標誌在命令行上傳遞它們,例如:
docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
九、ADD
ADD
指令用於複製新文件、目錄或遠程文件 URL 到容器 路徑中。可以指定多個資源,但如果它們是文件或目錄,則它們的路徑被解釋爲相對於構建上下文的源,也就是 WORKDIR。
ADD
指令有兩種形式:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
每個都 可能包含通配符,匹配將使用 Go 的 filepath.Match 規則。 是一個絕對路徑,或相對 WORKDIR 的相對路徑。例如:
添加所有以 “hom” 開頭的文件:
ADD hom* /mydir/
在下面的示例中,? 被替換爲任何單個字符,例如 “home.txt”。
ADD hom?.txt /mydir/
所有新創建的文件和目錄的 UID 和 GID 都爲 0,除非使用--chown
指定 UID/GID 以及權限。-chown
特性僅在用於構建 Linux 容器。
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
如果 是一個可識別壓縮格式(identity、gzip、bzip2 或 xz)的本地 tar 存檔,那麼它將被解包爲一個目錄。遠程 URL 中的資源不會解壓縮。當一個目錄被複制或解包時,它的行爲與tar -x
相同。
十、COPY
COPY 指令和 ADD 指令的唯一區別在於:是否支持從遠程 URL 獲取資源。COPY 指令只能從執行 docker build 所在的主機上讀取資源並複製到鏡像中。而 ADD 指令還支持通過 URL 從遠程服務器讀取資源並複製到鏡像中。
相同複製命令下,使用 ADD 構建的鏡像比 COPY 命令構建的體積大,所以如果只是複製文件使用 COPY 命令。ADD 指令更擅長讀取本地 tar 文件並解壓縮。
十一、ENTRYPOINT
ENTRYPOINT
和CMD
一樣,都是在指定容器啓動程序以及參數,不會它不會被docker run
的命令行指令所覆蓋。如果要覆蓋的話需要通過docker run --entrypoint
來指定。
ENTRYPOINT 有兩種形式:
ENTRYPOINT ["exec","param1","param1"]
ENTRYPOINT command param1 param2
指定了 ENTRYPOINT 後,CMD 的內容作爲參數傳遞給 ENTRYPOINT 指令,實際執行時將變爲:
十二、VOLUME
創建一個具有指定名稱的掛載數據卷。
VOLUME ["/var/log/"]
VOLUME /var/log
VOLUME 的主要作用是:
-
避免重要的數據因容器重啓而丟失。
-
避免容器不斷變大。
-
保留配置文件。
十三、ONBUILD
ONBUILD
指令作爲觸發指令添加到鏡像中,只有在該鏡像作爲基礎鏡像時執行。觸發器將在下游構建的 Dockerfile 中的FROM
指令之後執行。如果任何觸發器失敗,FROM
指令將中止,從而導致生成失敗。如果所有觸發器都成功,FROM
指令將完成,構建將照常繼續。
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
注意,ONBUILD 指令不能觸發 FORM 和 MAINTAINER 指令。
十四、STOPSIGNAL
設置容器退出時喚起的系統調用信號。該信號可以是與內核系統調用表中的位置匹配的有效無符號數字,例如 9,或格式爲 SIGNAME 的信號名稱,如 SIGKILL。
STOPSIGNAL signal
默認的 stop-signal 是 SIGTERM,在docker stop
的時候會給容器內 PID 爲 1 的進程發送這個信號,通過--stop-signal
可以設置需要的 signal,主要用於讓容器內的程序在接收到 signal 之後可以先處理些未完成的事務,實現優雅結束進程後退出容器。如果不做任何處理,容器將在一段時間後強制退出,可能會造成業務強制中斷,默認時間是 10s。
十五、HEALTHCHECK
HEALTHCHECK
指令告訴容器如何檢查它是否保持運行。當容器具有指定的HEALTHCHECK
時,除了其正常狀態外,還具有健康狀態。容器的狀態最初是starting
,只要通過健康檢查,容器的狀態就變成healthy
(無論之前處於什麼狀態)。如果經過一定數量的失敗檢查,容器的狀態會變成unhealthy
。
該HEALTHCHECK
指令有兩種形式:
-
HEALTHCHECK [OPTIONS] CMD command:通過容器內運行命令來檢查容器健康狀況。後面命令的退出狀態會影響容器的健康狀態,如:
-
0: success - 容器是健康的,並且準備使用
-
1: unhealthy - 容器沒有正確工作
-
2: reserved - 沒有使用退出狀態
-
HEALTHCHECK NONE:禁用從基礎鏡像繼承的任何健康檢查。
HEALTHCHECK
選項(應處於CMD
之前):
-
--interval=DURATION
:檢查間隔,default:30s
。 -
--timeout=DURATION
:檢查超時時間,超出此範圍認爲檢查失敗,default:30s
。 -
--start-period=DURATION
:容器初始化階段的時間,此階段健康檢查失敗不計入最大重試次數,如果檢查成功則認爲容器已啓動,default:0s
。 -
--retries=N
:健康檢查連續失敗次數,default:3
。
舉例:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
十六、SHELL
SHELL
指令用於設置默認 shell。Linux 上默認 shell 是["/bin/sh","-c"]
,Windows 上是["cmd","/S","/C"]
。
SHELL ["exec","param1"]
SHELL
指令在 Windows 上特別有用,因爲 Windows 有兩種截然不同的本機 SHELL:CMD 和 powershell,以及備用的 sh。該 SHELL 指令可以出現多次。每條 SHELL 指令都會覆蓋所有先前的 SHELL 指令,並影響後續指令。
FROM
Learn more about the "FROM" Dockerfile command.
microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
十七、WORKDIR
WORKDIR
指令爲 Dockerfile 中接下來的RUN
、CMD
、ENTRYPOINT
、ADD
、COPY
指令設置工作目錄。如果WORKDIR
不存在,及時它沒有在後續 Dockerfile 指令中使用,它也會被創建。
Dockerfile 中可以多次使用WORKDIR
,如果提供了相對路徑,它將相對於前一條WORKDIR
指令的路徑。
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終 pwd 命令的輸出是 /a/b/c。
該 WORKDIR 指令可以解析先前使用 ENV,例如:
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
最終 pwd 命令的輸出是 /path/$DIRNAME。
官方推薦 WORKDIR 始終使用絕對路徑。此外,儘量避免使用
RUN cd ..&& dosomething
,大量的類似指令會降低可讀性,令 Dockerfile 難以維護。
十八、USER
RUN
指令設置用戶名或(UID)和可選用戶組(或 GID),用於運行Dockerfile
中接下來的RUN
、CMD
、ENTRYPOINT
指令。
USER <user>[:<group>]
USER <UID>[:<GID>]
注意,在 Linux 上,當用戶沒有主組時,鏡像(或指令)將與根組一起運行。在 Windows 上,如果用戶不是內置帳戶,則必須首先創建該用戶。也可以先通通過
net user
創建用戶,再指定用戶。FROM microsoft/windowsservercore # Create Windows user in the container RUN net user /add patrick # Set it for subsequent commands USER patrick
十九、MAINTAINER
MAINTAINER 指令設置生成鏡像的作者。如:
MAINTAINER <name>
官方文檔:
https://docs.docker.com/engine/reference/builder/#label
如果對文章內容存在疑問
歡迎各位移步到公衆號後臺留言。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/swiryyb9Azzr7fva5ISE9w