目錄
1. FROM 基于基礎鏡像構建
1.1 FROM 指令開頭
1.2 ARG和FROM使用
1.3 FROM可以多個
1.4? AS name
1.5 tag和digest
2. RUN 執行任何命令
2.1 shell和exec兩種使用方式
2.2 [OPTIONS]參數
3. CMD 指定默認執行命令
3.1 使用格式shell和exec兩種使用方式
3.2 只能有一個CMD指令
3.3 CMD可以在外部啟動容器時替換CMD中的命令
4. ENTRYPOINT 指定默認執行命令
5. CMD和ENTRYPOINT區別
6. LABEL 將元數據添加到鏡像中
7. MAINTAINER 指定生成的鏡像作者信息
8. EXPOSE docker運行時要監聽的端口號
9. ENV設置環境變量
10. ADD 添加本地和遠程文件目錄
11. COPY復制文件和目錄
12.? ADD和COPY指令在功能上是相似的,但目的略有不同。
13. VOLUME創建卷掛載
14. USER設定用戶名和群組ID
14.1 使用示例
第 1 步:創建 Dockerfile
第 2 步:構建 Docker 鏡像
第 3 步:運行 Docker 容器
第 4 步:驗證輸出
15. WORKDIR 設置工作目錄
16. ARG 構建鏡像時設置變量
16.1 ARG指令可以包含一個默認值
16.2 ARG變量有效范圍
16.3 ARG使用方式
16.14?docker預定義的ARG參數
17. ONBUILD 當前鏡像被其他鏡像使用的時候的觸發指令
18. STOPSIGNAL 指定在容器停止時發送給容器的信號
19. HEALTHCHECK 啟動時檢查容器的健康狀況
20. SHELL Set the default shell of an image.
1. FROM 基于基礎鏡像構建
FROM [--platform=<platform>] <image> [AS <name>]FROM [--platform=<platform>] <image>[:<tag>] [AS <name>FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
1.1 FROM 指令開頭
FROM 指令用于初始化一個新的構建階段,并為后續指令設置基礎鏡像。因此,有效的 Dockerfile 必須以 FROM 指令開頭。該鏡像可以是任何有效的鏡像。
1.2 ARG和FROM使用
在Dockerfile中,ARG是唯一可能位于FROM之前的指令。參見理解ARG和FROM是如何互動的。
dockerFile文件中,不論一個FROM還是多個FROM,如果from指令中要使用ARG定義的變量,只能使用第一個FROM指令前ARG定義的變量參數
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-appFROM extras:${CODE_VERSION}
CMD /code/run-extras
但如果我們想在FROM之后的命令中也想使用ARG定義的參數,就必須在FROM之后,再次用ARG指令引用參數名,只能引用參數名,而不能攜帶參數默認值
ARG VERSION=latest
FROM busybox:$VERSION
# 通過ARG 參數名 的方式 引用第一個from之前定義arg參數
ARG VERSION
RUN echo $VERSION > image_version
1.3 FROM可以多個
FROM可以在單個Dockerfile中出現多次,以創建多個鏡像
或者將一個構建階段用作另一個構建階段的引用依賴。只需在每個新的FROM指令之前記錄提交操作輸出的最后一個鏡像ID。
每個FROM指令清除由前一個指令創建的任何狀態。
1.4? AS name
FROM指令添加AS name為新的構建階段指定一個名稱,該名稱可以在后續的FROM構建階段中引用。引用方式如下:
FROM <name>COPY --from=<name>RUN --mount=type=bind,from=<name> # 例如# 第一階段:構建應用程序
FROM golang:1.16 AS builderWORKDIR /app# 拷貝應用程序的源代碼到容器中
COPY . .# 構建應用程序
RUN go build -o myapp# 第二階段:創建最終鏡像
FROM alpine:latestWORKDIR /app# 從第一階段復制構建好的應用程序到最終鏡像中
COPY --from=builder /app/myapp .# 設置應用程序的入口命令
CMD ["./myapp"]
在上面的示例中,Dockerfile分為兩個階段。第一階段使用golang:1.16作為基礎鏡像,將應用程序的源代碼復制到容器中,并在容器中構建應用程序。第二階段使用alpine:latest作為基礎鏡像,從第一階段復制構建好的應用程序到最終鏡像中,并設置應用程序的入口命令。
使用多階段構建可以減小最終鏡像的大小,因為第一階段只包含構建所需的依賴和工具,而不包含運行時所需的額外組件。最終鏡像只包含運行應用程序所需的最小組件,從而減小了鏡像的體積。
另外一個方式:
COPY --from=0 /app/ /app
編號是從0開始,排第幾就from幾
1.5 tag和digest
<image>[:<tag>]和<image>[@<digest>] 以上兩個參數可選,如果不使用這兩個值時,會使用latest版本的基礎鏡像
2. RUN 執行任何命令
RUN 后面可以添加任何指令,相當于在當前鏡像之上創建一個新層。添加的層在Dockerfile的下一步中使用。RUN有兩種形式:
# Shell form:
RUN [OPTIONS] <command> ...
# Exec form:
RUN [OPTIONS] [ "<command>", ... ]
2.1 shell和exec兩種使用方式
見之前介紹
(七)Dockerfile文件命令大全詳解_dockerfile命令詳解-CSDN博客文章瀏覽閱讀784次,點贊16次,收藏25次。dockerFile命令時史上全面詳細講解_dockerfile命令詳解https://blog.csdn.net/yilvqingtai/article/details/148692900
2.2 [OPTIONS]參數
使用見官方文檔:
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#run
3. CMD 指定默認執行命令
通過鏡像運行容器的時候,會執行CMD后面的命令
3.1 使用格式shell和exec兩種使用方式
CMD command param1 param2CMD ["executable","param1","param2"]
3.2 只能有一個CMD指令
一個Dockerfile中只能有一個CMD指令。如果您列出了多個CMD命令,則只有最后一個生效。
3.3 CMD可以在外部啟動容器時替換CMD中的命令
# dockerfile文件內容如下
FROM ubuntu:trusty
ENTRYPOINT ["ping"]
CMD ["-c", "20", "localhost"]
啟動容器的時候
docker run kaidemo6 -c 30 127.0.0.1
其中??-c 30 127.0.0.1? 就替換了dockerfile中CMD后面的???["-c", "20", "localhost"]
4. ENTRYPOINT 指定默認執行命令
用法基本上和CMD一樣,實際使用中二者結合使用,具體區別如下
5. CMD和ENTRYPOINT區別
(1)ENTRYPOINT 和 CMD 都可以單獨使用,指定啟動容器時所運行的命令以及參數。
(2)更常見的用法是把 ENTRYPOINT 和 CMD 組合使用:
- ENTRYPOINT 指定啟動容器時所運行的命令和不變的參數。在啟動容器時可以顯式覆蓋,但一般不這么做。
- ?CMD 指定運行參數。在啟動容器時可以顯式覆蓋。
(3)ENTRYPOINT 和 CMD 都強烈推薦使用“exec形式”。
具體參考博客
Dockerfile里的ENTRYPOINT和CMD_dockerfile entrypoint和cmd-CSDN博客文章瀏覽閱讀7k次,點贊40次,收藏44次。Dockerfile里的ENTRYPOINT和CMD_dockerfile entrypoint和cmdhttps://blog.csdn.net/duke_ding2/article/details/135418179
6. LABEL 將元數據添加到鏡像中
LABEL指令將元數據添加到鏡像中。LABEL是一個鍵值對。要在LABEL值中包含空格,請像在命令行解析中那樣使用引號和反斜杠。下面是一些用法示例:
LABEL <key>=<value> [<key>=<value>...]
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
一個鏡像可以添加多個標簽LABEL,以下兩種方式:
LABEL multi.label1="value1" multi.label2="value2" other="value3"LABEL multi.label1="value1" \multi.label2="value2" \other="value3"
7. MAINTAINER 指定生成的鏡像作者信息
維護者信息:作者啥的,可以多個
格式:MAINTAINER <name>
示例:MAINTAINER Juhe cnMAINTAINER juhecn@163.comMAINTAINER Juhe cn <juhecn@163.com>
建議使用LABEL指令進行設置, 更方便靈活,同時可以通過 docker? inspect 查看鏡像的元數據。
8. EXPOSE docker運行時要監聽的端口號
EXPOSE <port> [<port>/<protocol>...]
EXPOSE指令通知Docker容器在運行時監聽指定的網絡端口。您可以指定監聽的端口TCP還是UDP,如果不指定協議,則默認為TCP。
EXPOSE 80/tcp
EXPOSE 80/udp
EXPOSE指令實際上并不發布端口。它的作用是作為構建映像的人員和運行容器的人員之間的一種文檔,說明打算發布哪些端口。要在運行容器時發布端口,請在docker運行上使用-p標志來發布和映射一個或多個端口,或者使用-p標志來發布所有公開的端口并將其映射到高階端口。
docker run -p 80:80/tcp -p 80:80/udp ...
docker network命令支持在容器之間創建通信網絡,而不需要公開或發布特定的端口,因為連接到網絡的容器可以通過任何端口相互通信。
9. ENV設置環境變量
ENV <key>=<value> [<key>=<value>...]
使用方式:
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV指令允許多個<key>=<value>…變量一次設置:
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \MY_CAT=fluffy
?通過生成的鏡像運行容器時,可以使用使用docker run——env <key>=<value>來更改它們。
10. ADD 添加本地和遠程文件目錄
ADD指令從<src>復制新的文件或目錄,并將它們添加到鏡像文件系統中<dest>路徑下。
其中文件和目錄可以從構建上下文、遠程URL或Git存儲庫中復制。
兩種使用方式:其中如果路徑中帶有空格,使用第二種方式
ADD [OPTIONS] <src> ... <dest>
ADD [OPTIONS] ["<src>", ... "<dest>"]
- 可以指定多個源文件或目錄,但最后一個必須復制的目的地參數
ADD file1.txt file2.txt /usr/src/things/
如果指定了多個源文件,無論是直接指定還是使用通配符指定,那么目標文件必須是一個目錄(必須以斜杠/結尾)。
- 遠程地址或者git倉庫地址復制
ADD https://example.com/archive.zip /usr/src/things/
ADD git@github.com:user/repo.git /usr/src/things/
- 從構建的上下文中復制文件
任何不以http://、https://或git@協議前綴開頭的相對路徑或本地路徑都被認為是本地文件路徑。
本地文件路徑是相對于構建上下文的。
例如,如果構建上下文是當前目錄,ADD file.txt / 將位于? ./file.txt 的文件添加到構建容器中文件系統的根目錄。
- 指定帶有斜杠的源路徑,或者在構建上下文之外導航的源路徑,
例如? ?ADD ../something /something,自動刪除所有父目錄導航(../)。源路徑中的尾斜杠也會被忽略,使? ? ADD something/ /something? ? 等同于? ? ADD something/ something? ??
- 模式匹配
要在構建上下文的根目錄中添加所有以.png結尾的文件和目錄:?
ADD *.png /dest/
在下面的例子中,?是一個單字符通配符,匹配例如index.js和index.ts
ADD index.?s /dest/
在添加包含特殊字符(如[和])的文件或目錄時,需要按照Golang規則轉義這些路徑,以防止它們被視為匹配模式。例如,要添加一個名為arr[0].txt的文件,使用以下命令;
ADD arr[[]0].txt /dest/
更多見官方文檔
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#add
11. COPY復制文件和目錄
COPY有兩種形式。后一種形式是包含空格的路徑所必需的。
COPY [OPTIONS] <src> ... <dest>
COPY [OPTIONS] ["<src>", ... "<dest>"]
?[OPTIONS]參數:
參數 | Dockerfile最小支持版本 |
---|---|
--from | |
--chown | |
--chmod | 1.2 |
--link | 1.4 |
--parents | 1.7-labs |
--exclude | 1.7-labs |
具體間官方文檔:
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#copy
12.? ADD和COPY指令在功能上是相似的,但目的略有不同。
- ADD和COPY在功能上相似。
- COPY支持從構建上下文或從多階段構建中的一個階段將文件復制到容器中。
- ADD支持從遠程HTTPS和Git url獲取文件的特性,以及在從構建上下文添加文件時自動提取tar文件的特性
在多階段構建中,您通常希望使用COPY將文件從一個階段復制到另一個階段。如果您需要將構建上下文中的文件臨時添加到容器中以執行RUN指令,那么您通常可以用綁定掛載代替COPY指令。例如,要臨時為RUN pip安裝指令添加一個requirements.txt文件:
RUN --mount=type=bind,source=requirements.txt,target=/tmp/requirements.txt \pip install --requirement /tmp/requirements.txt
13. VOLUME創建卷掛載
您應該使用VOLUME指令來公開由Docker容器創建的任何數據庫存儲區域、配置存儲或文件和文件夾。
強烈建議您對映像中可變部分或用戶可服務部分的任何組合使用VOLUME。
VOLUME ["/data"]
14. USER設定用戶名和群組ID
USER <user>[:<group>]USER <UID>[:<GID>]
默認情況下,Docker 容器以 Root 用戶身份運行。如果您在 Docker 容器內大規模部署應用程序,這會帶來巨大的安全威脅。您可以使用USER指令更改或切換到 Docker 容器內的不同用戶。為此,您首先需要在容器內創建一個用戶和一個組。
14.1 使用示例
我們將使用USER指令將容器內的用戶從 Root 切換到我們將創建的用戶。
-
第 1 步:創建 Dockerfile
您可以在Dockerfile中指定創建新用戶和組以及切換用戶的指令。在此示例中,我們將簡單地創建一個 Ubuntu 映像,并通過除 Root 用戶之外的其他用戶來使用 bash。
FROM ubuntu:latest
RUN apt-get -y update
RUN groupadd -r user && useradd -r -g user user
USER user
在上面的dockerfile中,我們已經拉取了基礎鏡像 Ubuntu 并更新了它。我們創建了一個名為user的新組,并在該組內創建了一個具有相同名稱的新用戶。使用USER選項,我們已經切換了用戶。
-
第 2 步:構建 Docker 鏡像
創建Dockerfile后,我們現在可以使用 Build 命令創建 Docker 映像。
sudo docker build -t user-demo
-
第 3 步:運行 Docker 容器
使用 Docker Run 命令來運行容器。
sudo docker run -it user-demo bash
第 4 步:驗證輸出
現在,您可以使用id命令檢查默認用戶和組是否已更改為我們在Dockerfile中創建的用戶和組。
id
使用Dockerfile中的USER指令將 Docker 容器的默認用戶從 Root 切換到我們可以使用useradd和groupadd命令創建的另一個用戶。?
15. WORKDIR 設置工作目錄
WORKDIR /path/to/workdir
- 使用RUN、CMD、ENTRYPOINT、COPY和ADD指令,需要使用前先設定工作目錄,因此可通過WORKDIR指令預先設置工作目錄。如果不設置,Dockerfile仍然會默認創建
- Dockerfile文件中可以使用多個WORKDIR指令。
- 如果WORKDIR后面跟隨的相對路徑,其相對的路徑是根據上一個WORKDIR指令的路徑
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
輸出結果? /a/b/c??
- WORKDIR指令參數可以引用ENV變量
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
輸出結果:??/path/$DIRNAME
- 如果未指定,則默認工作目錄為/
- 如果我們dockerfile中沒有用?FROM scratch? 指令,而是基于?FROM baseiamge,那么工作目錄通常是由基礎鏡像決定的。所以使用過程中,dockerfile中最好顯式設定
“FROM scratch”是指構建一個完全空的鏡像。這種方式通常用于構建小而輕量的容器,特別適合Go、Rust等編譯為靜態可執行文件的語言。使用
scratch
鏡像的好處包括:
- 更小的體積:由于沒有多余的庫和工具,最終生成的鏡像體積可以大幅減少。
- 控制性更強:開發者可以完全控制鏡像中的內容,避免不必要的依賴和安全風險。
16. ARG 構建鏡像時設置變量
ARG <name>[=<default value>] [<name>[=<default value>]...]
ARG指令定義了一個變量,用戶可以在構建時使用? docker build? 命令? --build-ARG? <varname>=<value>? 標志將該變量傳遞給構建器。
一個dockerfile文件中可以有多個ARG指令。
16.1 ARG指令可以包含一個默認值
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
docker build 時如果傳遞了值,該值會覆蓋默認值
16.2 ARG變量有效范圍
ARG生命后,開始起效
FROM busybox
USER ${username:-some_user}
ARG username
USER $username
# ...
調用方式
docker build --build-arg username=what_user .
第2行上的USER指令計算結果為some_user,因為還沒有聲明username變量。
第3行定義了username變量,從此位置往后,Dockerfile指令中就可以引用該變量
第4行USER的值是
what_user
,此時username參數有一個在命令行上傳遞的what_user值在ARG指令定義username變量之前,對username變量的任何使用都會導致一個空字符串。
在多個構建階段的dockerfile中,在A階段ARG聲明的變量x,如果構建時B階段繼承了A階段,那么B階段也繼承并共享A階段的變量x,B階段在使用的時候可以直接引用變量。相反,如果C階段沒有繼承A階段,那么必須通過ARG x? 的方式,引用才能夠使用,否則無法使用。具體參加下圖:
16.3 ARG使用方式
- ARG和ENV使用覆蓋
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER
ENV會覆蓋ARG參數值。
執行以下命令后,打印結果是v1.0.0而不是v2.0.1 ,這是因為第三行局部作用域覆蓋了從其他方式傳遞的參數變量值。
docker build --build-arg CONT_IMG_VER=v2.0.1 .
16.14?docker預定義的ARG參數
Docker有一組預定義的ARG變量,你可以在Dockerfile中使用這些變量,而不需要相應的ARG指令。
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
ALL_PROXY
all_proxy
通過以下命令示例使用
docker build --build-arg HTTPS_PROXY=https://my-proxy.example.com .
其他更多ARG指令使用見官方文檔
Dockerfile reference | Docker DocsFind all the available commands you can use in a Dockerfile and learn how to use them, including COPY, ARG, ENTRYPOINT, and more.https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope
17. ONBUILD 當前鏡像被其他鏡像使用的時候的觸發指令
ONBUILD <INSTRUCTION>
當鏡像A被用作其他構建階段的基礎鏡像的時候,會觸發 ONBUILD 后的指令動作。可以理解為一個觸發器。常用在一些不同配置或者守護進程中。
比如 某個鏡像構建的時候包括了這些ONBUILD指令,以下構建后新的鏡像名:alpine:baseimage
FROM alpine AS baseimage
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
此時如果其他構建基于上面鏡像構建:
FROM alpine:baseimage
后續就會執行 基礎鏡像中的ADD 和 RUN的指令操作。
常見使用場景:
- 應用程序構建: 基礎鏡像包含編譯環境(如 JDK、Maven、Node.js),
ONBUILD
?指令可以自動添加源代碼 (ONBUILD ADD . /app
) 并執行構建命令 (ONBUILD RUN mvn package
?或?ONBUILD RUN npm install
)。 - 標準化配置: 確保所有派生鏡像都包含特定的配置文件或設置。
- 依賴注入: 自動安裝特定于下游應用類型的依賴庫。
更多參考博客
理解 Dockerfile ONBUILD 指令:構建可擴展的基礎鏡像 - Leo-Yide - 博客園在 Dockerfile 的世界里,指令是構建鏡像藍圖的基石。除了常見的 FROM, RUN, COPY, CMD 等指令外,還有一個相對特殊但非常有用的指令——ONBUILD。ONBUILD 指令允許我們在基礎鏡像中定義一組“觸發”指令,這些指令在構建基礎鏡像時并不會執行,而是在任何 下游 鏡像(https://www.cnblogs.com/leojazz/p/18820017
18. STOPSIGNAL 指定在容器停止時發送給容器的信號
在Dockerfile中,STOPSIGNAL
?指令是用來指定在容器停止時發送給容器的信號。這在某些情況下很有用,比如你想要在容器停止時執行一些清理工作。
然而,值得注意的是,STOPSIGNAL
?指令已經被標記為不推薦使用(deprecated)并且在Docker的后續版本中可能會被移除。官方文檔推薦使用?CMD
?或?ENTRYPOINT
?指令來處理容器的啟動和停止邏輯。
19. HEALTHCHECK 啟動時檢查容器的健康狀況
指令告訴?Docker?如何測試一個容器,以檢查它是否仍在工作
Dockerfile中使用HEALTHCHECK的形式有兩種:?
1、HEALTHCHECK [options] CMD command
2、HEALTHCHECK NODE 意思是禁止從父鏡像繼承的HEALTHCHECK生效?
options的可設定參數:
interval:間隔(s秒、m分鐘、h小時),從容器運行起來開始計時interval秒(或者分鐘小時)進行第一次健康檢查,隨后每間隔interval秒進行一次健康檢查;還有一種特例請看timeout解析。
--start-period=DURATION 啟動時間, 默認 0s, 如果指定這個參數, 則必須大于 0s ;--start-period 為需要啟動的容器提供了初始化的時間段, 在這個時間段內如果檢查失敗, 則不會記錄失敗次數。 如果在啟動時間內成功執行了健康檢查, 則容器將被視為已經啟動, 如果在啟動時間內再次出現檢查失敗, 則會記錄失敗次數。
timeout:執行command需要時間,比如curl 一個地址,如果超過timeout秒則認為超時是錯誤的狀態,此時每次健康檢查的時間是timeout+interval秒。
retries:連續檢查retries次,如果結果都是失敗狀態,則認為這個容器是unhealth的
CMD關鍵字后面可以跟執行shell腳本的命令或者exec數組。CMD后面的命令執行完的返回值代表容器的運行狀況,可能的值:0 health狀態,1 unhealth狀態,2 reserved狀態,這個沒細研究,用的也很少。?
注意:在Dockerfile中只能有一個HEALTHCHECK指令。如果您列出多個,則只有最后一個HEALTHCHECK將生效。
20. SHELL 設置鏡像默認shell
SHELL ["executable", "parameters"]
默認dockerfile中shell命令是:
Linux 環境:["/bin/sh", "-c"]?
Windows 環境:["cmd", "/S", "/C"]
使用SHELL命令可以直接覆蓋。這尤其是在windows特別管用,因為window下有cmd和powershell兩種腳本命令
FROM 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
?