基本語法格式:INSTRUCTION arguments (指令+參數)不分大小寫
注釋格式:# 注釋
第一個指令必須是FROM,標示使用什么鏡像
1、解析器指令
解析器指令是可選的,並且影響處理Dockerfile中后續行的方式。 解析器指令不會向構建中添加圖層,並且不會顯示為構建步驟。 解析器指令以#directive = value的形式寫為特殊類型的注釋。 單個指令只能使用一次。
一旦注釋,空行或構建器指令已經被處理,Docker不再尋找解析器指令。 相反,它將格式化為解析器指令的任何內容視為注釋,並且不嘗試驗證它是否可能是解析器指令。 因此,所有解析器指令必須位於Dockerfile的最頂端。
解析器指令不區分大小寫。 然而,約定是他們是小寫的。 約定還要包括一個空白行,遵循任何解析器指令。 解析器指令不支持行連續字符。
由於這些規則,以下示例都無效:
- 行延續而無效:
# direc
tive=value - 重復出現
# directive=value1
# directive=value2 - 出現在構建指令后
FROM ImageName
# directive=value - 作為注釋處理,由於出現在不是解析器指令的注釋之后
# About my dockerfile
FROM ImageName
# directive=value - 未知指令由於未被識別而被視為注釋。 此外,由於出現在不是解析器指令的注釋之后,已知指令被視為注釋。
# unknowndirective=value
# knowndirective=value
在解析器指令中允許使用非換行符空格。 因此,以下行都被相同地處理
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
支持以下解析器指令:(目前就一個)
- escape
# escape=\ (反斜杠)
OR
# escape=` (反引號)
escape指令設置了用於在Dockerfile中轉義字符的字符。 如果未指定,則缺省轉義字符為
轉義字符既用於轉義行中的字符,也用於轉義換行符。 這允許Dockerfile指令跨越多行。 注意,不管escape解析器指令是否包括在Dockerfile中,在RUN命令中不執行轉義,除非在行的末尾。
將轉義字符設置為`在Windows上特別有用,其中\是目錄路徑分隔符。 `與Windows PowerShell一致。
2、環境變量替換
環境變量(使用ENV語句聲明)也可以在某些指令中用作要由Dockerfile解釋的變量。還可以處理轉義,以將類似變量的語法包含到語句中。
FROM busybox
ENV foo /bar
Dockerfile中的以下指令列表支持環境變量:
- ADD
- COPY
- ENV
- EXPOSE
- LABEL
- USER
- WORKDIR
- VOLUME
- STOPSIGNAL
- ONBUILD
3、.dockerignore 文件
在docker CLI將內容送到docker守護程序之前,它會在內容的根目錄中查找名為.dockerignore的文件。如果此文件存在,CLI將修改內容以排除與其中的模式匹配的文件和目錄。這有助於避免不必要地向守護程序發送大型或敏感文件和目錄,並可能使用ADD或COPY將其添加到映像。
CLI將.dockerignore文件解釋為換行符分隔的模式列表,類似於Unix shell的文件glob。為了匹配的目的,內容的根被認為是工作目錄和根目錄。例如,模式/ foo / bar和foo / bar都排除了PATH的foo子目錄或位於URL的git存儲庫根目錄中名為bar的文件或目錄。也不排除任何其他。
如果.dockerignore文件中的一行以第1列中的#開頭,則此行將被視為注釋,並在CLI解釋之前被忽略。
這里是一個例子.dockerignore文件:
# comment
*/temp*
*/*/temp*
temp?
此文件導致以下構建行為:
規則 | 行為 |
---|---|
# comment | 注釋 忽略 |
*/temp* | 排除其根目錄的任何直接子目錄中以temp開頭的文件和目錄。<br />例如,普通文件/somedir/temporary.txt被排除,<br />目錄/ somedir / temp也被排除。 |
*/*/temp* | 從根目錄下兩級的任何子目錄中排除以temp開頭的文件和目錄。<br /> 例如,排除了/somedir/subdir/temporary.txt。 |
temp? | 排除根目錄中名稱為temp的單字符擴展名的文件和目錄。 <br />例如,/ tempa和/ tempb被排除。 |
行開頭! (感嘆號)可用於排除例外。 以下是使用此機制的.dockerignore文件示例:
*.md
!README.md
放置! 異常規則影響行為:匹配特定文件的.dockerignore的最后一行確定它是包含還是排除。 請考慮以下示例:
*.md
!README*.md
README-secret.md
只排除了README-secret.md
*.md
README-secret.md
!README*.md
排除所有README開頭的.md文件
甚至可以使用.dockerignore文件來排除Dockerfile和.dockerignore文件。 這些文件仍然發送到守護程序,因為它需要它們來完成它的工作。 但是ADD和COPY命令不會將它們復制到映像。
最后,可能需要指定要包括在內容中的文件,而不是要排除的文件。 要實現這一點,指定*作為第一個模式,后面跟一個或多個! 異常模式。
4、FROM
FROM指令為后續指令設置基本鏡像。 因此,有效的Dockerfile必須具有FROM作為其第一條指令。 鏡像可以是任何有效的鏡像 - 通過從公共存儲庫拉取鏡像
FROM <image>
OR
FROM <image>:<tag>
OR
FROM <image>@<digest>
5、RUN
有兩種格式
- RUN 指令
- RUN ["指令", "參數1", "參數2"...](json格式,必須雙引號)
RUN指令將在當前鏡像之上的新層中執行任何命令,並提交結果。 生成的已提交映像將用於Dockerfile中的下一步。
分層RUN指令和生成提交符合Docker的核心概念,其中提交很方便,可以從鏡像歷史中的任何點創建容器,就像源代碼控制一樣。
exec形式使得可以避免shell字符串變化,以及使用不包含指定的shell可執行文件的基本映像來運行RUN命令。
可以使用SHELL命令更改shell窗體的默認shell。
在shell形式中,可以使用\(反斜杠)將單個RUN指令繼續到下一行。 例如,考慮這兩行:
RUN /bin/bash -c 'source $HOME/.bashrc;
echo $HOME'
當行形式:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
使用不同的shell,例如使用/bin/sh
RUN ["/bin/bash", "-c", "echo hello"]
用於RUN指令的高速緩存在下一次構建期間不會自動失效。 用於諸如RUN apt-get dist-upgrade之類的指令的高速緩存將在下一次構建期間被重用。 可以通過使用--no-cache標志(例如docker build --no-cache)使用於RUN指令的高速緩存無效,詳細參看:最佳實踐指南
已知問題(RUN)
問題783是關於在使用AUFS文件系統時可能發生的文件權限問題。 例如,您可能會在嘗試rm文件時注意到它。
對於具有最近aufs版本的系統(即,可以設置dirperm1安裝選項),docker將嘗試通過使用dirperm1選項安裝圖層來自動解決問題。 有關dirperm1選項的更多詳細信息,請參見aufs man page
如果您的系統不支持dirperm1,則該問題描述了一種解決方法。
6、CMD
格式:
- CMD ["executable","param1","param2"]
- CMD ["param1","param2"]
- CMD command param1 param2
在Dockerfile中只能有一個CMD指令。 如果您列出多個CMD,則只有最后一個CMD將生效。
CMD的主要目的是為執行容器提供默認值。 這些默認值可以包括可執行文件,或者它們可以省略可執行文件,在這種情況下,您還必須指定ENTRYPOINT指令。
CMD echo "This is a test." | wc -
CMD ["/usr/bin/wc","--help"]
7、LABEL
LABEL指令向鏡像添加元數據。 LABEL是鍵值對。 要在LABEL值中包含空格,請使用引號和反斜杠,就像在命令行解析中一樣。 幾個使用示例:
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信息,使用docker inspect指令,
"Labels": {
"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.",
"other": "value3"
},
8、MAINTAINER
MAINTAINER指令設置生成的鏡像的作者字段。 LABEL指令是一個更靈活的版本,你應該使用它,因為它可以設置任何所需的元數據,並可以很容易地查看,例如使用docker檢查。 要設置與MAINTAINER字段對應的標簽,您可以使用:
LABEL maintainer "SvenDowideit@home.org.au"
設置的數據,可以在docker inspect指令展示的數據的other選項中
9、EXPOSE
格式:EXPOSE prot port
EXPOSE指令通知Docker容器在運行時偵聽指定的網絡端口。 EXPOSE不會使主機的端口可訪問。 為此,必須使用-p標志發布一系列端口,或使用-P標志發布所有暴露的端口。 您可以公開一個端口號,並在另一個號碼外部發布。
要在主機系統上設置端口重定向,請參閱使用-P標志。 Docker網絡功能支持創建網絡,無需在網絡中公開端口,有關詳細信息,請參閱此 功能的概述)。
10、ENV
格式:ENV <key> <value> OR ENV <key>=<value> ...
ENV指令將環境變量<key>設置為值<value>。 此值將在所有“descendant”Dockerfile命令的環境中,並且可以在許多中被替換為inline。
ENV指令有兩種形式。 第一種形式,ENV <key> <value>,將單個變量設置為一個值。 第一個空格后面的整個字符串將被視為<value> - 包括空格和引號等字符。
第二種形式,ENV <key> = <value> ...,允許一次設置多個變量。 注意,第二種形式在語法中使用等號(=),而第一種形式不使用。 與命令行解析類似,引號和反斜杠可用於在值中包含空格。
ENV myName="John Doe" myDog=Rex\ The\ Dog
myCat=fluffy
OR
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
11、ADD
格式:ADD <src> <dest> OR ADD ["<src>", "<dest>"]
ADD指令從<src>復制新文件,目錄或遠程文件URL,並將它們添加到路徑<dest>的映像文件系統。
DD hom* /mydir/ # 添加全部以hom開頭的文件
ADD hom?.txt /mydir/ # ? 代表單個任意字符
ADD遵守以下規則:
- <src>路徑必須在構建的上下文中; 你不能ADD ../something /東西,因為docker build的第一步是發送上下文目錄(和子目錄)到docker守護進程。
- 如果<src>是URL並且<dest>不以尾部斜杠結尾,則從URL下載文件並將其復制到<dest>。
- 如果<src>是URL並且<dest>以尾部斜杠結尾,則從URL中推斷文件名,並將文件下載到<dest> / <filename>。 例如,ADD http://example.com/foobar /會創建文件/ foobar。 該網址必須有一個非平凡的路徑,以便在這種情況下可以發現一個適當的文件名(http://example.com不會工作)。
- 如果<src>是目錄,則復制目錄的全部內容,包括文件系統元數據。
12、COPY
格式:COPY <src> <dest> OR COPY ["<src>", "<dest>"]
COPY指令從<src>復制新文件或目錄,並將它們添加到容器的文件系統,路徑<dest>。
可以指定多個<src>資源,但它們必須是相對於正在構建的源目錄
COPY hom* /mydir/
COPY hom?.txt /mydir/
COPY遵守以下規則:
- <src>路徑必須在構建的目錄中; 你不能COPY ../something / something,因為docker build的第一步是將當前目錄(和子目錄)發送到docker守護進程。
- 如果<src>是目錄,則復制目錄的全部內容,包括文件系統元數據。
13、ENTRYPOINT
格式:
- ENTRYPOINT ["executable", "param1", "param2"]
- ENTRYPOINT command param1 param2
ENTRYPOINT允許您配置將作為可執行文件運行的容器。
例如:下面將啟動 nginx,監聽80端口
docker run -i -t --rm -p 80:80 nginx
docker run <image>的命令行參數將附加在exec形式的ENTRYPOINT中的所有元素之后,並將覆蓋使用CMD指定的所有元素。 這允許將參數傳遞到入口點,即docker run <image> -d將把-d參數傳遞給入口點。 您可以使用docker run --entrypoint標志覆蓋ENTRYPOINT指令。
shell形式防止使用任何CMD或運行命令行參數,但缺點是您的ENTRYPOINT將作為/ bin / sh -c的子命令啟動,它不傳遞信號。 這意味着可執行文件將不是容器的PID 1,並且不會接收Unix信號,因此您的可執行文件將不會從docker stop <container>接收到SIGTERM。
只有Dockerfile中最后一個ENTRYPOINT指令會有效果。
您可以使用ENTRYPOINT的exec形式設置相當穩定的默認命令和參數,然后使用任一形式的CMD設置更可能更改的其他默認值。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
以下Dockerfile顯示使用ENTRYPOINT在前台運行Apache
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
最后,如果需要在關閉時進行一些額外的清理(或與其他容器通信),或者協調多個可執行文件,您可能需要確保ENTRYPOINT腳本接收到Unix信號,傳遞它們,然后 做一些更多的工作:
14、VOLUME
格式:VOLUM ["/data"]
VOLUME指令創建具有指定名稱的裝入點,並將其標記為從本機主機或其他容器保存外部裝入的卷。 該值可以是JSON數組VOLUME [“/ var / log /”]或具有多個參數的純字符串,例如VOLUME / var / log或VOLUME / var / log / var / db。 有關通過Docker客戶端的更多信息/示例和安裝說明,請參閱文檔
docker run命令用存在於基本映像中指定位置的任何數據初始化新創建的卷。 例如,考慮以下Dockerfile片段:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
此Dockerfile導致導致docker運行的映像,在/ myvol中創建新的安裝點,並將greeting文件復制到新創建的卷中。
15、USER
USER daemon
USER指令設置運行映像時使用的用戶名或UID,以及Dockerfile中的任何RUN,CMD和ENTRYPOINT指令。
16、WORKDIR
WORKDIR /path/to/workdir
WORKDIR指令為Dockerfile中的任何RUN,CMD,ENTRYPOINT,COPY和ADD指令設置工作目錄。 如果WORKDIR不存在,它將被創建,即使它沒有在任何后續的Dockerfile指令中使用。
它可以在一個Dockerfile中多次使用。 如果提供了相對路徑,它將相對於先前WORKDIR指令的路徑。 例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
最終輸出 /a/b/c
WORKDIR指令可以解析先前使用ENV設置的環境變量。 您只能使用在Dockerfile中顯式設置的環境變量。 例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
輸出 /path/$DIRNAME
17、ARG
格式:ARG <name>[=<default value>]
ARG指令定義一個變量,用戶可以使用docker build命令使用--build-arg <varname> = <value>標志,在構建時將其傳遞給構建器。 如果用戶指定未在Dockerfile中定義的構建參數,構建將輸出警告。例如:
FROM busybox
USER ${user:-some_user}
ARG user
USER $user
構建時:docker build --build-arg user=what_user Dockerfile
您可以使用ARG或ENV指令來指定RUN指令可用的變量。 使用ENV指令定義的環境變量總是覆蓋同名的ARG指令。 考慮這個帶有ENV和ARG指令的Dockerfile。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER v1.0.0
RUN echo $CONT_IMG_VER
docker build --build-arg CONT_IMG_VER=v2.0.1 Dockerfile
輸出:v1.0.0
18、ONBUILD
格式:ONBUIL 指令
ONBUILD指令在鏡像被用作另一個構建的基礎時,向鏡像添加要在以后執行的觸發指令。觸發器將在下游構建的上下文中執行,就好像它已經在下游Dockerfile中的FROM指令之后立即插入。
任何構建指令都可以注冊為觸發器。
如果您正在構建一個將用作構建其他映像的基礎,例如應用程序構建環境或可以使用用戶特定配置進行定制的守護程序,這將非常有用。
例如,如果您的映像是可重用的Python應用程序構建器,則需要將應用程序源代碼添加到特定目錄中,並且可能需要在此之后調用構建腳本。你不能只是調用ADD和RUN現在,因為你還沒有訪問應用程序源代碼,它將是不同的每個應用程序構建。您可以簡單地為應用程序開發人員提供一個樣板Dockerfile以將其復制粘貼到其應用程序中,但這是低效,容易出錯的並且難以更新,因為它與特定於應用程序的代碼混合在一起。
解決方案是使用ONBUILD來注冊提前指令,以便稍后在下一個構建階段運行。
以下是它的工作原理:
- 當遇到ONBUILD指令時,構建器會向正在構建的鏡像的元數據添加觸發器。 該指令不會另外影響當前構建。
- 在構建結束時,所有觸發器的列表存儲在圖像清單中的鍵OnBuild下。 可以使用docker inspect命令檢查它們。
- 稍后,可以使用FROM指令將鏡像用作新構建的基礎。 作為處理FROM指令的一部分,下游構建器會查找ONBUILD觸發器,並按照它們注冊的順序執行它們。 如果任何觸發器失敗,則FROM指令中止,這又導致構建失敗。 如果所有觸發器都成功,則FROM指令完成,並且構建如常繼續。
- 觸發器在執行后從最終鏡像中清除。 換句話說,它們不會被“grand-children”構建繼承。
19、STOPSIGNAL
格式:STOPSIGNAL signal
STOPSIGNAL指令設置將發送到容器以退出的系統調用信號。 該信號可以是與內核系統調用表中的位置匹配的有效無符號數,例如9,或者是SIGNAME格式的信號名稱,例如SIGKILL。
20、HEALTHCHECK
格式:
- HEALTHCHECK [OPTIONS] CMD command通過在容器中運行命令來檢查容器運行狀況
- HEALTHCHECK NONE 禁用從基本映像繼承的任何健康檢查
HEALTHCHECK指令告訴Docker如何測試容器以檢查它是否仍在工作。 這可以檢測到諸如Web服務器被卡在無限循環中並且無法處理新連接的情況,即使服務器進程仍在運行。
當容器指定了healthcheck時,除了其正常狀態外,它還具有健康狀態。 此狀態最初開始。 每當健康檢查通過,它變得健康(無論之前的狀態)。 在一定數量的連續故障后,它變得不健康。
可選參數:
- --interval=DURATION (默認30s) 30s檢查一次
- --timeout=DURATION (默認: 30s) 超過30s,認定檢查失敗
- --retries=N (默認: 3) 嘗試3次,認定容器不健康
命令的退出狀態表示容器的運行狀況。 可能的值是:
- 0 成功,健康
- 1 不健康
- 2 保留 不要用此退出代碼
例:
HEALTHCHECK --interval=5m --timeout=3s
CMD curl -f http://localhost/ || exit 1
21、SHELL
格式:SHELL ["命令", "參數"]
SHELL指令允許用於命令的shell形式的默認shell被覆蓋。 Linux上的默認shell是[“/ bin / sh”,“-c”],在Windows上是[“cmd”,“/ S”,“/ C”]。 SHELL指令必須以JSON形式寫在Dockerfile中。
SHELL指令在Windows上特別有用,其中有兩個常用的和完全不同的本機shell:cmd和powershell,以及包括sh的備用shell。
SHELL指令可以多次出現。 每個SHELL指令覆蓋所有先前的SHELL指令,並影響所有后續指令。 例如:
FROM microsoft/windowsservercore
RUN echo default
RUN powershell -command Write-Host default
SHELL ["powershell", "-command"]
RUN Write-Host hello
SHELL ["cmd", "/S"", "/C"]
RUN echo hello
鏈接:https://www.jianshu.com/p/46db3c909fdf
來源:簡書