Dockerfile
是由一系列命令和參數構成的腳本,一個Dockerfile
裏面包含了構建整個image
的完整命令。Docker經過docker build
執行Dockerfile
中的一系列命令自動構建image
。html
Dockerfile
其語法很是簡單,此頁面描述了您能夠在Dockerfile中使用的命令。 閱讀此頁面後,你能夠參閱Dockerfile最佳實踐。python
docker build
命令從Dockerfile
和context
構建image。context
是PATH
或URL
處的文件。PATH
本地文件目錄。 URL
是Git repository的位置。mysql
context
以遞歸方式處理。所以,PATH
包括任何子目錄,URL
包括repository及submodules。一個使用當前目錄做爲context
的簡單構建命令:linux
$ docker build .
Sending build context to Docker daemon 6.51 MB
...
複製代碼
構建由Docker守護程序運行,而不是由CLI運行。構建過程所作的第一件事是將整個context(遞歸地)發送給守護進程。大多數狀況下,最好是將Dockerfile
和所需文件複製到一個空的目錄,再到這個目錄進行構建。nginx
警告
:不要使用根目錄/
做爲PATH,由於它會致使構建將硬盤驅動器的全部內容傳輸到Docker守護程序。git
build時添加文件,經過Dockerfile
引用指令中指定的文件,例如COPY
指令。要增長構建的性能,請經過將.dockerignore
文件添加到context
目錄中來排除文件和目錄。有關如何建立.dockerignore文件的信息,請參閱此頁上的文檔。github
通常的,Dockerfile
位於context
的根中。但使用-f
標誌可指定Dockerfile的位置。golang
$ docker build -f /path/to/a/Dockerfile .
複製代碼
若是build成功,您能夠指定要保存新image的repository和tag:web
$ docker build -t shykes/myapp .
複製代碼
要在構建後將image標記爲多個repositories,請在運行構建命令時添加多個-t
參數:redis
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
複製代碼
Docker守護程序一個接一個地運行Dockerfile
中的指令,若是須要,將每一個指令的結果提交到一個新image,最後輸出新映像的ID。Docker守護進程將自動清理您發送的context。
請注意,每一個指令獨立運行,並致使建立一個新image - 所以RUN cd / tmp
對下一個指令不會有任何影響。
只要有可能,Docker將從新使用中間images(緩存),以顯着加速docker build
過程。這由控制檯輸出中的使用緩存消息指示。(有關詳細信息,請參閱Dockerfile
最佳實踐指南構建緩存部分):
$ docker build -t svendowideit/ambassador .
Sending build context to Docker daemon 15.36 kB
Step 1 : FROM alpine:3.2
---> 31f630c65071
Step 2 : MAINTAINER SvenDowideit@home.org.au
---> Using cache
---> 2a1c91448f5f
Step 3 : RUN apk update && apk add socat && rm -r /var/cache/
---> Using cache
---> 21ed6e7fbb73
Step 4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
---> Using cache
---> 7ea8aef582cc
Successfully built 7ea8aef582cc
複製代碼
構建成功後,就能夠準備Pushing a repository to its registry。
Dockerfile
的格式以下:
# Comment
INSTRUCTION arguments
複製代碼
INSTRUCTION
是不區分大小寫的,不過建議大寫。
Dockerfile中的指令第一個指令必需是
FROM`,指定構建鏡像的Base Image。
Dockerfile中以#
開頭的行都將視爲註釋,除非是[Parser directives]()解析器指令。不支持連續註釋符。
# Comment
RUN echo 'we are running some # of cool things'
複製代碼
解析器指令是可選的,而且影響處理Dockerfile
中後續行的方式。解析器指令不會向構建中添加圖層,而且不會顯示在構建步驟。解析器指令是以# directive = value
形式寫成一種特殊類型的註釋。單個指令只能使用一次。
一旦註釋,空行或構建器指令已經被處理,Docker再也不尋找解析器指令。相反,它將任何格式化爲解析器指令做爲註釋,而且不嘗試驗證它是否多是解析器指令。所以,全部解析器指令必須位於Dockerfile
的最頂端。
解析器指令不區分大小寫。然而,約定是他們是小寫的。公約還要包括一個空白行,遵循任何解析器指令。解析器指令不支持行連續字符。
因爲這些規則,如下示例都無效:
因行延續,無效:
# direc \
tive=value
複製代碼
因出現兩次,無效:
# directive=value1
# directive=value2
FROM ImageName
複製代碼
因寫在構建指令後,無效:
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=\ (backslash)
或者
# escape=` (backtick)
複製代碼
escape
指令設置用於在Dockerfile
中轉義字符的字符。若是未指定,則缺省轉義字符爲\
。
轉義字符既用於轉義行中的字符,也用於轉義換行符。這容許Dockerfile
指令跨越多行。注意,無論escape
解析器指令是否包括在Dockerfile
中,在RUN
命令中不執行轉義,除非在行的末尾。
將轉義字符設置爲 ` 在Windows
上特別有用,其中\
是目錄路徑分隔符。 ` 與Windows PowerShell一致。
請考慮如下示例,這將在Windows
上以非顯而易見的方式失敗。第二行末尾的第二個\
將被解釋爲換行符,而不是從第一個\
轉義的目標。相似地,假設第三行結尾處的\
實際上做爲一條指令處理,它將被視爲行繼續。這個dockerfile
的結果是第二行和第三行被認爲是單個指令:
FROM windowsservercore
COPY testfile.txt c:\\
RUN dir c:\
複製代碼
結果是:
PS C:\John> docker build -t cmd .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM windowsservercore
---> dbfee88ee9fd
Step 2 : COPY testfile.txt c:RUN dir c:
GetFileAttributesEx c:RUN: The system cannot find the file specified.
PS C:\John>
複製代碼
上述的一個解決方案是使用/
做爲COPY
指令和dir
的目標。然而,這種語法,最好的狀況是混亂,由於它在Windows
上是不日常的路徑,最壞的狀況下,錯誤傾向,由於並非Windows
上的全部命令支持/
做爲路徑分隔符。
經過添加轉義解析器指令,下面的Dockerfile在Windows上使用文件路徑的天然平臺語義成功:
# escape=`
FROM windowsservercore
COPY testfile.txt c:\
RUN dir c:\
複製代碼
結果是:
PS C:\John> docker build -t succeeds --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM windowsservercore
---> dbfee88ee9fd
Step 2 : COPY testfile.txt c:\
---> 99ceb62e90df
Removing intermediate container 62afbe726221
Step 3 : RUN dir c:\
---> Running in a5ff53ad6323
Volume in drive C has no label.
Volume Serial Number is 1440-27FA
Directory of c:\
03/25/2016 05:28 AM <DIR> inetpub
03/25/2016 04:22 AM <DIR> PerfLogs
04/22/2016 10:59 PM <DIR> Program Files
03/25/2016 04:22 AM <DIR> Program Files (x86)
04/18/2016 09:26 AM 4 testfile.txt
04/22/2016 10:59 PM <DIR> Users
04/22/2016 10:59 PM <DIR> Windows
1 File(s) 4 bytes
6 Dir(s) 21,252,689,920 bytes free
---> 2569aa19abef
Removing intermediate container a5ff53ad6323
Successfully built 2569aa19abef
PS C:\John>
複製代碼
環境變量(使用ENV語句聲明)也能夠在某些指令中用做要由Dockerfile
解釋的變量。還能夠處理轉義,以將相似變量的語法包含在語句中。
環境變量在Dockerfile
中用$variable_name
或${variable_name}
表示。它們被等同對待,而且括號語法一般用於解決不帶空格的變量名的問題,例如${foo}_bar
。
${variable_name}
語法還支持如下指定的一些標準bash
修飾符:
${variable:-word}
表示若是設置了variable
,則結果將是該值。若是variable
未設置,那麼word
將是結果。${variable:+word}
表示若是設置了variable
,那麼word
將是結果,不然結果是空字符串。在全部狀況下,word
能夠是任何字符串,包括額外的環境變量。
能夠經過在變量以前添加\
來轉義:\$foo
或\${foo}
,分別轉換爲$foo
和${foo}
。
示例(解析的表示顯示在#
後面):
FROM busybox
ENV foo /bar
WORKDIR ${foo} # WORKDIR /bar
ADD . $foo # ADD . /bar
COPY \$foo /quux # COPY $foo /quux
複製代碼
Dockerfile
中的如下指令列表支持環境變量:
以及:
注意
:在1.4以前,ONBUILD
指令不支持環境變量,即便與上面列出的任何指令相結合。
環境變量替換將在整個命令中對每一個變量使用相同的值。換句話說,在這個例子中:
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
複製代碼
將致使def
值爲hello
,再也不bye
。然而,ghi
的值爲bye
,由於它不是設置abc
爲bye
的相同命令的一部分。
在docker CLI將上下文發送到docker守護程序以前,它會在上下文的根目錄中查找名爲.dockerignore
的文件。若是此文件存在,CLI將修改上下文以排除匹配其中模式的文件和目錄。這有助於避免沒必要要地向守護程序發送大型或敏感文件和目錄,並可能使用ADD
或COPY
將其添加到映像。
CLI將.dockerignore
文件解釋爲換行符分隔的模式列表,相似於Unix shell
的file globs。爲了匹配的目的,上下文的根被認爲是工做目錄和根目錄。例如,模式/foo/bar
和foo/bar
都排除了PATH
的foo
子目錄中的名爲bar
的文件或目錄,或者位於URL
處的git repository的根目錄中。也不排除任何其餘。
若是.dockerignore
文件中的一行以第1列中以#
開頭,則此行被視爲註釋,並在CLI解釋以前被忽略。
這裏是一個例子.dockerignore
文件:
# comment
*/temp*
*/*/temp*
temp?
複製代碼
此文件致使如下構建行爲:
規則 | 行爲 |
---|---|
# comment |
忽略 |
*/temp* |
在根的任何直接子目錄中排除其名稱以temp開頭的文件和目錄。 例如,普通文件/somedir/temporary.txt被排除,目錄/somedir/temp也被排除。 |
*/*/temp* |
從根目錄下兩級的任何子目錄中排除以temp開頭的文件和目錄。 例如,排除了/somedir/subdir/temporary.txt。 |
temp? |
排除根目錄中名稱爲temp的單字符擴展名的文件和目錄。 例如,/tempa和/tempb被排除。 |
匹配是使用Go的filepath.Match規則完成的。 預處理步驟刪除前導和尾隨空格並消除.
和..
元素使用Go的filepath.Clean。預處理後爲空的行將被忽略。
除了Go的filepath.Match規則,Docker還支持一個特殊的通配符字符串**
,它匹配任何數量的目錄(包括零)。 例如,**/*.go
將排除全部目錄中找到的以.go
結尾的全部文件,包括構建上下文的根。
行開頭!
(感嘆號)可用於排除例外。 如下是使用此機制的.dockerignore
文件示例:
*.md
!README.md
複製代碼
除了README.md
以外的全部markdown文件都從上下文中排除。
放置!
異常規則影響行爲:匹配特定文件的.dockerignore
的最後一行肯定它是包括仍是排除。思考下面的例子:
*.md
!README*.md
README-secret.md
複製代碼
除了README-secret.md
以外的README
文件,上下文中排除全部markdown文件。
如今思考這個例子:
*.md
README-secret.md
!README*.md
複製代碼
包括全部README文件。 中間行沒有效果,由於最後的!README*.md
與README-secret.md
匹配。
您甚至可使用.dockerignore
文件來排除Dockerfile
和.dockerignore
文件。這些文件仍然發送到守護程序,由於它須要它們來完成它的工做。可是ADD
和COPY
命令不會將它們複製到映像。
最後,您可能須要指定要包括在上下文中的文件,而不是要排除的文件。 要實現這一點,指定*
做爲第一個模式,後面跟一個或多個!
異常模式。
注意
:因爲歷史緣由.
模式。被忽略。
FROM <image>
# 或則
FROM <image>:<tag>
# 或則
FROM <image>@<digest>
複製代碼
FROM
指令爲後續指令設置Base Image。所以,有效的Dockerfile
必須具備FROM
做爲其第一條指令。image能夠是任何有效的image - 能夠從Public Repositoriespulling an image。
FROM
必須是Dockerfile
中的第一個非註釋指令。FROM
能夠在單個Dockerfile
中屢次出現,以建立多個圖像。只需記下在每一個新的FROM
命令以前由提交輸出的最後一個image ID。tag
或digest
是可選的。若是省略其中任何一個,構建器將默認使用latest
。若是構建器與tag
值不匹配,則構建器將返回錯誤。MAINTAINER <name>
複製代碼
MAINTAINER
指令容許您設置生成的images的做者字段。
RUN有2種形式:
RUN <command>
(*shell*形式,命令在shell中運行,Linux上爲/bin/sh -c
,Windows上爲cmd /S/C
)RUN ["executable","param1","param2"]
(
RUN
指令將在當前image之上的新層中執行任何命令,並提交結果。生成的已提交image將用於Dockerfile
中的下一步。
分層RUN
指令和生成提交符合Docker的核心概念,其中提交很輕量,能夠從image歷史中的任何點建立容器,就像源代碼控制同樣。
exec
形式使得能夠避免shell字符串變化,以及使用不包含指定的shell可執行文件的基本image來運行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’,請使用在所需shell中傳遞的exec形式。例如,RUN [「/bin/bash」,「-c」,「echo hello」]
注意
:exec形式做爲JSON數組解析,這意味着您必須在單詞以外使用雙引號(」)而不是單引號(’)。
注意
:與shell表單不一樣,exec表單不調用命令shell。這意味着正常的shell處理不會發生。例如,RUN ["echo","$HOME"]
不會在$HOME
上進行可變替換。若是你想要shell處理,那麼使用shell形式或直接執行一個shell,例如:RUN ["sh","-c","echo $HOME"]
。當使用exec形式並直接執行shell時,正如shell形式的狀況,它是作環境變量擴展的shell,而不是docker。
注意
:在JSON形式中,有必要轉義反斜槓。這在Windows上特別相關,其中反斜槓是路徑分隔符。由於不是有效的JSON,而且以意外的方式失敗,如下行將被視爲shell形式:RUN ["c:\windows\system32\tasklist.exe"]
此示例的正確語法爲:RUN ["c:\\windows\\system32\\tasklist.exe"]
用於RUN
指令的高速緩存在下一次構建期間不會自動失效。用於諸如RUN apt-get dist-upgrade
之類的指令的高速緩存將在下一次構建期間被重用。能夠經過使用--no-cache
標誌來使用於RUN
指令的高速緩存無效,例如docker build --no-cache
。
有關詳細信息,請參閱Dockerfile最佳實踐指南。
用於RUN
指令的高速緩存能夠經過ADD
指令無效。有關詳細信息,請參見下文。
Known issues(RUN)
rm
文件時注意到它。對於具備最近aufs版本的系統(即,能夠設置dirperm1
安裝選項),docker將嘗試經過使用dirperm1
選項安裝image來自動解決問題。有關dirperm1
選項的更多詳細信息,請參見aufs手冊頁 若是您的系統不支持dirperm1
,則該問題描述了一種解決方法。CMD指令三種形式:
CMD ["executable","param1","param2"]
(
CMD ["param1","param2"]
(as default parameters to
CMD command param1 param2
(
在Dockerfile
中只能有一個CMD
指令。若是您列出多個CMD
,則只有最後一個CMD
將生效。
CMD
的主要目的是爲執行容器提供默認值。這些默認值能夠包括可執行文件,或者它們能夠省略可執行文件,在這種狀況下,您還必須指定ENTRYPOINT
指令。
注意
:若是使用CMD
爲ENTRYPOINT
指令提供默認參數,CMD
和ENTRYPOINT
指令都應以JSON數組格式指定。
注意
:exec形式做爲JSON數組解析,這意味着您必須在單詞以外使用雙引號(」)而不是單引號(’)。
注意
:與shell表單不一樣,exec表單不調用命令shell。這意味着正常的shell處理不會發生。例如,CMD ["echo","$HOME"]
不會在$HOME
上進行可變替換。若是你想要shell處理,那麼使用shell形式或直接執行一個shell,例如:CMD ["sh","-c","echo $HOME"]
。當使用exec形式並直接執行shell時,正如shell形式的狀況,它是作環境變量擴展的shell,而不是docker。
當以shell或exec格式使用時,CMD
指令設置運行image時要執行的命令。
若是使用CMD
的shell形式,那麼<command>
將在/bin/sh -c
中執行:
FROM ubuntu
CMD echo "This is a test." | wc -
複製代碼
若是你想運行你的<command>
沒有shell,那麼你必須將該命令表示爲一個JSON數組,並給出可執行文件的完整路徑。此數組形式是CMD
的首選格式。任何其餘參數必須單獨表示爲數組中的字符串:
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
複製代碼
若是你但願你的容器每次運行相同的可執行文件,那麼你應該考慮使用ENTRYPOINT結合CMD。 請參閱ENTRYPOINT。
若是用戶指定docker run
參數,那麼它們將覆蓋CMD
中指定的默認值。
注意
:不要將RUN
和CMD
混淆。RUN
實際上運行一個命令並提交結果;CMD
在構建時不執行任何操做,但指定了image的預期命令。
LABEL <key>=<value> <key>=<value> <key>=<value> ...
複製代碼
LABEL
指令向image添加元數據。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."
複製代碼
image能夠有多個label。要指定多個label,Docker建議在可能的狀況下將標籤合併到單個LABEL
指令中。每一個LABEL
指令產生一個新層,若是使用許多標籤,可能會致使效率低下的圖像。該示例產生單個圖像層。
LABEL multi.label1="value1" multi.label2="value2" other="value3"
複製代碼
上面的也可寫爲:
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
複製代碼
標籤是添加的,包括LABEL
在FROM
images中。若是Docker遇到已經存在的label/key,則新值將覆蓋具備相同鍵的任何先前標籤。
要查看image的labels,請使用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.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
},
複製代碼
EXPOSE <port> [<port>...]
複製代碼
EXPOSE
指令通知Docker容器在運行時偵聽指定的網絡端口。EXPOSE
不使主機的容器的端口可訪問。爲此,必須使用-p
標誌發佈一系列端口,或者使用-P
標誌發佈全部暴露的端口。您能夠公開一個端口號,並用另外一個端口號在外部發布。
要在主機系統上設置端口重定向,請參閱使用-P標誌。Docker網絡功能支持建立網絡,無需在網絡中公開端口,有關詳細信息,請參閱此功能的概述)。
ENV <key> <value>
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
# 和
ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy
複製代碼
將在最終容器中產生相同的淨結果,但第一種形式是優選的,由於它產生單個高速緩存層。
使用ENV
設置的環境變量將在從生成的image運行容器時保留。您可使用docker inspect
查看值,並使用docker run --env <key> = <value>
更改它們。
注意
:環境持久性可能會致使意外的反作用。例如,將ENV DEBIAN_FRONTEND
設置爲非交互式可能會使apt-get用戶混淆基於Debian的映像。要爲單個命令設置值,請使用RUN <key> = <value> <command>
。
兩種形式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]
(對於包含空格的路徑,此形式是必需的)ADD
指令從<src>
複製新文件,目錄或遠程文件URL
,並將它們添加到容器的文件系統,路徑<dest>
。
能夠指定多個<src>
資源,但若是它們是文件或目錄,那麼它們必須是相對於正在構建的源目錄(構建的context)。
每一個<src>
可能包含通配符,匹配將使用Go的filepath.Match規則完成。 例如:
ADD hom* /mydir/ # adds all files starting with "hom"
ADD hom?.txt /mydir/ # ? is replaced with any single character, e.g., "home.txt"
複製代碼
<dest>
是絕對路徑或相對於WORKDIR
的路徑,源將在目標容器中複製到其中。
ADD test relativeDir/ # adds "test" to `WORKDIR`/relativeDir/
ADD test /absoluteDir/ # adds "test" to /absoluteDir/
複製代碼
全部新文件和目錄都使用UID和GID爲0建立。
在<src>
是遠程文件URL
的狀況下,目標將具備600的權限。若是正在檢索的遠程文件具備HTTP Last-Modified
標頭,則來自該標頭的時間戳將用於設置目的地上的mtime
文件。然而,像在ADD
期間處理的任何其它文件同樣,mtime
將不包括在肯定文件是否已經改變而且高速緩存應該被更新。
注意
:若是經過傳遞一個Dockerfile
經過STDIN(docker build - <somefile
)構建,沒有構建上下文,因此Dockerfile
只能包含一個基於URL的ADD
指令。您還能夠經過STDIN傳遞壓縮歸檔文件:(docker build - <archive.tar.gz
),歸檔根目錄下的Dockerfile
和歸檔的其他部分將在構建的上下文中使用。
注意
:若是您的URL文件使用身份驗證保護,則您須要使用RUN wget
,RUN curl
或從容器內使用其餘工具,由於ADD指令不支持身份驗證。
注意
:若是<src>
的內容已更改,第一個遇到的ADD
指令將使來自Dockerfile
的全部後續指令的高速緩存無效。這包括使用於RUN指令的高速緩存無效。有關詳細信息,請參閱Dockerfile最佳實踐指南。
ADD
遵照如下規則:
<src>
路徑必須在構建的上下文中;你不能ADD ../something /something
,由於docker構建的第一步是發送上下文目錄(和子目錄)到docker守護進程。若是<src>
是URL而且<dest>
不以尾部斜槓結尾,則從URL下載文件並將其複製到<dest>
。<src>
是URL而且<dest>
以尾部斜槓結尾,則從URL中推斷文件名,並將文件下載到<dest>/<filename>
。例如,ADD http://example.com/foobar /
會建立文件/ foobar
。網址必須有一個非平凡的路徑,以便在這種狀況下能夠發現一個適當的文件名(http://example.com
不會工做)。<src>
是目錄,則複製目錄的整個內容,包括文件系統元數據。
注意
:目錄自己不被複制,只是其內容。
<src>
是識別的壓縮格式(identity,gzip,bzip2或xz)的本地tar存檔,則將其解包爲目錄。來自遠程URL的資源不會解壓縮。當目錄被複制或解壓縮時,它具備與tar -x
相同的行爲:結果是如下的聯合:
注意
:文件是否被識別爲識別的壓縮格式,僅基於文件的內容,而不是文件的名稱。例如,若是一個空文件以.tar.gz結尾,則不會被識別爲壓縮文件,而且不會生成任何解壓縮錯誤消息,而是將該文件簡單地複製到目的地。
<src>
是任何其餘類型的文件,它會與其元數據一塊兒單獨複製。在這種狀況下,若是<dest>
以尾部斜槓/
結尾,它將被認爲是一個目錄,而且<src>
的內容將被寫在<dest>/base(<src>)
。<src>
資源,則<dest>
必須是目錄,而且必須以斜槓/
結尾。<dest>
不以尾部斜槓結尾,它將被視爲常規文件,<src>
的內容將寫在<dest>
。<dest>
不存在,則會與其路徑中的全部缺乏的目錄一塊兒建立。兩種形式:
COPY <src>... <dest>
COPY ["<src>",... "<dest>"]
(this form is required for paths containing whitespace)基本和ADD相似,不過COPY
的<src>
不能爲URL。
兩種形式:
ENTRYPOINT
容許您配置容器,運行執行的可執行文件。
例如,如下將使用其默認內容啓動nginx,偵聽端口80:
docker run -i -t --rm -p 80:80 nginx
複製代碼
docker run <image>
的命令行參數將附跟在
ENTRYPOINT
中的全部元素以後,並將覆蓋使用
CMD
指定的全部元素。這容許將參數傳遞到入口點,即
docker run <image> -d
將把
-d
參數傳遞給入口點。您可使用
docker run --entrypoint
標誌覆蓋
ENTRYPOINT
指令。
CMD
或運行命令行參數,可是缺點是您的
ENTRYPOINT
將做
/bin/sh -c
的子命令啓動,它不傳遞信號。這意味着可執行文件將不是容器的
PID 1
,而且不會接收Unix信號,所以您的可執行文件將不會從
docker stop <container>
接收到
SIGTERM
。
只有Dockerfile
中最後一個ENTRYPOINT
指令會有效果。
Exec form ENTRYPOINT example
您可使用ENTRYPOINT
的*exec*形式設置至關穩定的默認命令和參數,而後使用任一形式的CMD
設置更可能更改的其餘默認值。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
複製代碼
運行容器時,您能夠看到top是惟一的進程:
$ docker run -it --rm --name test top -H
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
複製代碼
要進一步檢查結果,可使用docker exec
:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
複製代碼
而且你能夠優雅地請求top
使用docker stop test
關閉。
如下Dockerfile
顯示使用ENTRYPOINT
在前臺運行Apache
(即,做爲PID 1
):
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"]
複製代碼
若是須要爲單個可執行文件編寫啓動腳本,可使用exec
和gosu
命令確保最終可執行文件接收到Unix信號:
#!/bin/bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"
複製代碼
最後,若是須要在關閉時進行一些額外的清理(或與其餘容器通訊),或者協調多個可執行文件,您可能須要確保ENTRYPOINT
腳本接收到Unix信號,傳遞它們,而後作一些更多的工做:
#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too
# USE the trap if you need to also do manual cleanup after the service is stopped,
# or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM
# start service in background here
/usr/sbin/apachectl start
echo "[hit enter key to exit] or run 'docker stop <container>'"
read
# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop
echo "exited $0"
複製代碼
若是你用docker run -it --rm -p 80:80 --name test apache
運行image,則可使用·docker exec·或·docker top·檢查容器的進程,而後請求腳本中止Apache:
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
$ docker top test
PID USER COMMAND
10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2
10054 root /usr/sbin/apache2 -k start
10055 33 /usr/sbin/apache2 -k start
10056 33 /usr/sbin/apache2 -k start
$ /usr/bin/time docker stop test
test
real 0m 0.27s
user 0m 0.03s
sys 0m 0.03s
複製代碼
注意
:您可使用--entrypoint
覆蓋ENTRYPOINT
設置,但這隻能將二進制設置爲*exec*(不使用sh -c
)。
注意
:*exec*形式做爲JSON數組解析,這意味着您必須在單詞以外使用雙引號(」)而不是單引號(’)。
注意
:與shell
形式不一樣,*exec*形式不調用命令shell。這意味着正常的shell處理不會發生。例如,ENTRYPOINT ["echo","$ HOME"]
不會在$HOME
上進行可變替換。若是你想要shell處理,那麼使用shell形式或直接執行一個shell,例如:ENTRYPOINT ["sh","-c","echo $HOME"]
。當使用exec形式並直接執行shell時,正如shell形式的狀況,它是作環境變量擴展的shell,而不是docker。
Shell form ENTRYPOINT example
您能夠爲ENTRYPOINT
指定一個純字符串,它將在/bin/sh -c
中執行。這中形式將使用shell處理來替換shell環境變量,而且將忽略任何CMD
或docker run
命令行參數。要確保docker stop
將正確地發出任何長時間運行的ENTRYPOINT
可執行文件,您須要記住用exec
啓動它:
FROM ubuntu
ENTRYPOINT exec top -b
複製代碼
運行此image時,您將看到單個PID 1
進程:
$ docker run -it --rm --name test top
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
Load average: 0.08 0.03 0.05 2/98 6
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root R 3164 0% 0% top -b
複製代碼
它獎在docker stop
乾淨的退出:
$ /usr/bin/time docker stop test
test
real 0m 0.20s
user 0m 0.02s
sys 0m 0.04s
複製代碼
若是忘記將exec
添加到您的ENTRYPOINT
的開頭:
FROM ubuntu
ENTRYPOINT top -b
CMD --ignored-param1
複製代碼
而後,您能夠運行它(給它一個名稱爲下一步):
$ docker run -it --name test top --ignored-param2
Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq
Load average: 0.01 0.02 0.05 2/101 7
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2
7 1 root R 3164 0% 0% top -b
複製代碼
您能夠從top的輸出中看到指定的ENTRYPOINT不是PID 1。
若是你而後運行docker中止測試,容器將不會徹底退出 - 中止命令將強制發送SIGKILL超時後:
$ docker exec -it test ps aux
PID USER COMMAND
1 root /bin/sh -c top -b cmd cmd2
7 root top -b
8 root ps aux
$ /usr/bin/time docker stop test
test
real 0m 10.19s
user 0m 0.04s
sys 0m 0.03s
複製代碼
Understand how CMD and ENTRYPOINT interact
CMD
和ENTRYPOINT
指令定義在運行容器時執行什麼命令。這裏有較少的規則描述他們的合做。
Dockerfile
應該至少指定一個CMD
或ENTRYPOINT
命令。ENTRYPOINT
。CMD
應該用做定義ENTRYPOINT
命令的默認參數或在容器中執行ad-hoc命令的一種方法。CMD
將被覆蓋。下表顯示了對不一樣ENTRYPOINT
/CMD
組合執行的命令:
no ENTRYPOINT | ENTRYPOINT exec_enty p1_entry | ENTRYPOINT [「exec_entry」,「p1_entry」] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [「exec_cmd」,「p1_cmd」] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry exec_cmd p1_cmd | exec_entry p1_entry exec_cmd p1_cmd |
CMD [「p1_cmd」, 「p2_cmd」] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry p1_cmd p2_cmd | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
VOLUME ["/data"]
複製代碼
VOLUME
指令建立具備指定名稱的掛載點,並將其標記爲從本機主機或其餘容器保留外部掛載的卷。該值能夠是JSON數組VOLUME ["/var/log/"]
或具備多個參數的純字符串,例如VOLUME /var/log
或VOLUME /var/log /var/db
。有關經過Docker客戶端的更多信息/示例和安裝說明,請參閱經過卷文檔共享目錄。
docker run
命令用存在於基本image中指定位置的任何數據初始化新建立的卷。例如,思考如下Dockerfile
片斷:
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
複製代碼
此Dockerfile docker run
的映像,在/myvol
上建立一個新的掛載點,並將greeting
文件複製到新建立的卷中。
注意
:若是任何構建步驟在聲明後更改卷中的數據,那麼這些更改將被丟棄。
注意
:該列表解析爲JSON數組,這意味着您必須在單詞以外使用雙引號(」)而不是單引號(’)。
USER daemon
複製代碼
USER
指令設置運行image時使用的用戶名或UID,以及Dockerfile
中的任何RUN,CMD
和ENTRYPOINT
指令。
WORKDIR /path/to/workdir
複製代碼
WORKDIR
指令爲Dockerfile
中的任何RUN
,CMD
,ENTRYPOINT
,COPY
和ADD
指令設置工做目錄。若是WORKDIR
不存在,它將被建立,即便它沒有在任何後續的Dockerfile
指令中使用。
它能夠在一個Dockerfile
中屢次使用。若是提供了相對路徑,它將相對於先前WORKDIR指令的路徑。 例如:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
複製代碼
在這個Dockerfile
中的最終pwd
命令的輸出是/a/b/c
。
WORKDIR
指令能夠解析先前使用ENV
設置的環境變量。您只能使用在Dockerfile
中顯式設置的環境變量。 例如:
ENV DIRPATH /path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
複製代碼
pwd
命令在該Dockerfile
中輸出的最後結果是/path/$DIRNAME
。
ARG <name>[=<default value>]
複製代碼
ARG
指令定義一個變量,用戶可使用docker build
命令使用--build-arg <varname> = <value>
標誌,在構建時將其傳遞給構建器。若是用戶指定了一個未在Dockerfile
中定義的構建參數,構建將輸出錯誤。
One or more build-args were not consumed, failing build.
複製代碼
Dockerfile做者能夠經過指定ARG
一個或多個變量,經過屢次指定ARG
來定義單個變量。例如,一個有效的Dockerfile
:
FROM busybox
ARG user1
ARG buildno
...
複製代碼
Dockerfile做者能夠可選地指定ARG
指令的默認值:
FROM busybox
ARG user1=someuser
ARG buildno=1
...
複製代碼
若是ARG
值具備缺省值,而且若是在構建時沒有傳遞值,則構建器使用缺省值。
ARG
變量定義從在Dockerfile
中定義的行開始生效,而不是從命令行或其餘地方的參數使用。例如,考慮這個Dockerfile:
1 FROM busybox
2 USER ${user:-some_user}
3 ARG user
4 USER $user
...
複製代碼
用戶構建此文件以下:
$ docker build --build-arg user=what_user Dockerfile
複製代碼
第2行的USER
將評估爲some_user
,由於用戶變量在後續行3上定義。第4行的USER
在定義用戶時估計爲what_user
,在命令行中傳遞what_user
值。在經過ARG
指令定義以前,變量的任何使用都將致使空字符串。
警告
:不建議使用build-time變量來傳遞諸如github密鑰,用戶憑證等密碼。構建時變量值使用docker history
命令對圖像的任何用戶可見。
可使用ARG
或ENV
指令來指定RUN
指令可用的變量。使用ENV
指令定義的環境變量老是覆蓋同名的ARG
指令。思考這個Dockerfile
帶有ENV
和ARG
指令。
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER v1.0.0
4 RUN echo $CONT_IMG_VER
複製代碼
而後,假設此image是使用此命令構建的:
$ docker build --build-arg CONT_IMG_VER=v2.0.1 Dockerfile
複製代碼
在這種狀況下,RUN
指令使用v1.0.0
而不是用戶傳遞的ARG
設置:v2.0.1
此行爲相似於shell腳本,其中本地做用域變量覆蓋做爲參數傳遞或從環境繼承的變量,從其定義點。
使用上述示例,但使用不一樣的ENV
規範,您能夠在ARG
和ENV
指令之間建立更有用的交互:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER ${CONT_IMG_VER:-v1.0.0}
4 RUN echo $CONT_IMG_VER
複製代碼
與ARG
指令不一樣,ENV
值始終保留在image中。考慮一個沒有-build-arg
標誌的docker構建:
$ docker build Dockerfile
複製代碼
使用這個Dockerfile示例,CONT_IMG_VER
仍然保留在映像中,但它的值將是v1.0.0
,由於它是ENV
指令在第3行中的默認設置。
此示例中的變量擴展技術容許您從命令行傳遞參數,並經過利用ENV
指令將它們持久保存在最終image中。僅對一組有限的Dockerfile指令支持變量擴展。
Docker有一組預約義的ARG
變量,您能夠在Dockerfile中使用相應的ARG指令。
要使用這些,只需在命令行使用標誌傳遞它們:
--build-arg <varname>=<value>
複製代碼
Impact on build caching
ARG
變量不會持久化到構建的image中,由於ENV
變量是。可是,ARG
變量會以相似的方式影響構建緩存。若是一個Dockerfile
定義一個ARG
變量,它的值不一樣於之前的版本,那麼在它的第一次使用時會出現一個「cache miss」,而不是它的定義。特別地,在ARG
指令以後的全部RUN
指令都隱式地使用ARG變量(做爲環境變量),所以可能致使高速緩存未命中。
例如,考慮這兩個Dockerfile:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 RUN echo $CONT_IMG_VER
複製代碼
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 RUN echo hello
複製代碼
若是在命令行上指定--build-arg CONT_IMG_VER = <value>
,則在這兩種狀況下,第2行的規範不會致使高速緩存未命中;行3確實致使高速緩存未命中。ARG CONT_IMG_VER
致使RUN
行被標識爲與運行CONT_IMG_VER = <value> echo hello
相同,所以若是<value>
更改,咱們將獲得高速緩存未命中。
考慮在同一命令行下的另外一個示例:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER $CONT_IMG_VER
4 RUN echo $CONT_IMG_VER
複製代碼
在此示例中,高速緩存未命中發生在第3行。因爲變量在ENV
中的值引用ARG
變量而且該變量經過命令行更改,所以發生了未命中。在此示例中,ENV
命令使image包括該值。
若是ENV
指令覆蓋同名的ARG
指令,就像這個Dockerfile:
1 FROM ubuntu
2 ARG CONT_IMG_VER
3 ENV CONT_IMG_VER hello
4 RUN echo $CONT_IMG_VER
複製代碼
第3行不會致使高速緩存未命中,由於CONT_IMG_VER
的值是一個常量(hello)。所以,RUN
(第4行)上使用的環境變量和值在構建之間不會更改。
ONBUILD [INSTRUCTION]
複製代碼
ONBUILD
指令在image被用做另外一個構建的基礎時,向image添加要在之後執行的*trigger*指令。trigger將在下游構建的上下文中執行,就好像它已經在下游Dockerfile中的1FROM1指令以後當即插入。
任何構建指令均可以註冊爲trigger。
若是您正在構建將用做構建其餘image的基礎的圖像,例如應用程序構建環境或可使用用戶特定配置自定義的後臺駐留程序,這將很是有用。
例如,若是您的image是可重用的Python應用程序構建器,則須要將應用程序源代碼添加到特定目錄中,而且可能須要在此以後調用構建腳本。你不能只是調用ADD
和RUN
如今,由於你尚未訪問應用程序源代碼,它將是不一樣的每一個應用程序構建。您能夠簡單地爲應用程序開發人員提供一個樣板Dockerfile以將其複製粘貼到其應用程序中,但這是低效,容易出錯,而且很難更新,由於它與應用程序特定的代碼混合。
解決方案是使用ONBUILD
來註冊提早指令,以便稍後在下一個構建階段運行。
如下是它的工做原理:
ONBUILD
指令時,構建器會向正在構建的image的元數據添加trigger。該指令不會另外影響當前構建。docker inspect
命令檢查它們。FROM
指令將image用做新構建的基礎。做爲處理FROM
指令的一部分,下游構建器會查找ONBUILD
triggers,並按照它們註冊的順序執行它們。若是任何觸發器失敗,則FROM
指令停止,這又致使構建失敗。若是全部觸發器都成功,則FROM
指令完成而且構建如常繼續。觸發器在執行後從最終image中清除。換句話說,它們不會被「grand-children」構建繼承。 例如,您能夠添加以下: [...] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src [...]
> 警告
:不容許使用ONBUILD ONBUILD
連接ONBUILD
指令。 > 警告
:ONBUILD
指令可能不會觸發FROM
或MAINTAINER
指令。STOPSIGNAL signal
複製代碼
STOPSIGNAL
指令設置將發送到容器以退出的系統調用信號。該信號能夠是與內核系統調用表中的位置匹配的有效無符號數,例如9,或者是SIGNAME格式的信號名稱,例如SIGKILL。
兩種形式:
HEALTHCHECK
指令告訴Docker如何測試容器以檢查它是否仍在工做。這能夠檢測到諸如Web服務器被卡在無限循環中而且沒法處理新鏈接的狀況,即便服務器進程仍在運行。
當容器指定了healthcheck時,除了其正常狀態外,它還具備健康狀態。此狀態最初開始。 每當健康檢查經過,它變得健康(不管以前的狀態)。在必定數量的連續故障後,它變得不健康。
在CMD以前能夠出現的選項有:
--interval=DURATION
(default: 30s)--timeout=DURATION
(default: 30s)--retries=N
(default: 3)運行情況檢查將首先在容器啓動後運行interval秒,而後在每次上次檢查完成後再次運行interval秒。
若是檢查的單次運行所花費的時間超過timeout秒數,則該檢查被認爲已失敗。
它須要retries連續的健康檢查的故障,容器被認爲是不健康的。
在Dockerfile中只能有一個HEALTHCHECK
指令。若是您列出多個,則只有最後一個HEALTHCHECK
將生效。
CMD
關鍵字以後的命令能夠是shell命令(例如HEALTHCHECK CMD /bin/check-running
)或exec數組(如同其餘Dockerfile命令同樣;詳情參見ENTRYPOINT
)。
命令的退出狀態表示容器的運行情況。 可能的值爲:
例如,要每五分鐘檢查一次Web服務器可以在三秒鐘內爲網站的主頁提供服務:
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
複製代碼
爲了幫助調試失敗的探測器,命令在stdout或stderr上寫入的任何輸出文本(UTF-8編碼)將存儲在運行情況狀態,並可使用docker inspect
查詢。這樣的輸出應該保持短路(只存儲當前的4096個字節)。
當容器的運行情況發生更改時,將生成具備新狀態的health_status
事件。
HEALTHCHECK
功能在Docker 1.12中添加。
SHELL ["executable", "parameters"]
複製代碼
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 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 複製代碼
如下指令可能受SHELL
指令的影響,當它們的shell形式用於Dockerfile:RUN
,CMD
和ENTRYPOINT
。
如下示例是Windows上的常見模式,可使用SHELL指令進行簡化:
...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...
複製代碼
docker調用的命令將是:
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
複製代碼
這是低效的,有兩個緣由。首先,有一個沒必要要的cmd.exe命令處理器(也稱爲shell)被調用。其次,shell中的每一個RUN
指令都須要一個額外的powershell -command
。
爲了更有效率,能夠採用兩種機制之一。 一種是使用JSON形式的RUN命令,如:
...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...
複製代碼
雖然JSON形式是明確的,而且不使用沒必要要的cmd.exe,但它須要經過雙引號和轉義更詳細。 備用機制是使用SHELL
指令和shell形式,爲Windows用戶提供更天然的語法,特別是與escape
解析指令結合使用時:
# escape=`
FROM windowsservercore
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
複製代碼
結果是:
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 3.584 kB
Step 1 : FROM windowsservercore
---> 5bc36a335344
Step 2 : SHELL powershell -command
---> Running in 87d7a64c9751
---> 4327358436c1
Removing intermediate container 87d7a64c9751
Step 3 : RUN New-Item -ItemType Directory C:\Example
---> Running in 3e6ba16b8df9
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 6/2/2016 2:59 PM Example
---> 1f1dfdcec085
Removing intermediate container 3e6ba16b8df9
Step 4 : ADD Execute-MyCmdlet.ps1 c:\example\
---> 6770b4c17f29
Removing intermediate container b139e34291dc
Step 5 : RUN c:\example\Execute-MyCmdlet -sample 'hello world'
---> Running in abdcf50dfd1f
Hello from Execute-MyCmdlet.ps1 - passed hello world
---> ba0e25255fda
Removing intermediate container abdcf50dfd1f
Successfully built ba0e25255fda
PS E:\docker\build\shell>
複製代碼
SHELL
指令還能夠用於修改外殼操做的方式。例如,在Windows上使用SHELL cmd /S /C /V:ON|OFF
,能夠修改延遲的環境變量擴展語義。
SHELL
指令也能夠在Linux上使用,若是須要一個替代shell,如zsh
,csh
,tcsh
和其餘。
SHELL
功能在Docker 1.12中添加。
下面你能夠看到一些Dockerfile語法的例子。 若是你對更現實的東西感興趣,能夠看看Dockerization的例子。
# Nginx
#
# VERSION 0.0.1
FROM ubuntu
MAINTAINER Victor Vieux <victor@docker.com>
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
複製代碼
# Firefox over VNC
#
# VERSION 0.3
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
複製代碼
# Multiple images example
#
# VERSION 0.1
FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f
FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4
# You᾿ll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.複製代碼
Compose file 是一個YAML文件,用於定義 services, networks, 和 volumes。其默認路徑是./docker-compose.yml
一個service定義包含了這個服務啓動的全部容器的配置,這個操做看起來很像是傳遞命令行參數給docker container create命令。一樣,network和volume定義相似於docker network create 和 docker volume create命令。
與 docker container create 同樣,在Dockerfile中指定的選項(好比:CMD、 EXPOSE、 VOLUME、 ENV等)也是同樣的,你不須要在docker-compose.yml中再次指定它們。
1.1. build
應用於構建時的配置選項
build指定了構建上下文路徑
或者,也能夠用一個包含context和可選的dockerfile及args的對象類指定
若是在指定build的同時還指定了image,那麼將會用指定的鏡像來構建
1.2. context
指向包含Dockerfile目錄的路徑,或者指向git倉庫的url
若是這個值是相對路徑,那麼它相對的是compose file所在的位置(PS:其實就是當前目錄)
1.3. Dockerfile
你也能夠用Dockerfile來構建,不過這個時候必須指定context
(PS:dockerfile是用來生成鏡像的,也就是說構建的時候能夠從image構建,也能夠從dockerfile構建,是同樣的)
1.4. args
添加構建參數,這些環境變量只能在構建過程當中訪問
首先,在Dockerfile中定義變量
而後,在構建的時候給這些變量賦值
或者,下面這種寫法也是能夠的
注意:若是在Dockerfile中,ARG在FROM指令以前,那麼在FROM指令下ARG不可用
你也能夠在構建參數中省略它們的值,這種狀況下會從Compose運行的環境中取值(PS:其實就是環境變量)
1.5. cache_from
緩存的鏡像列表
1.6. shm_size
爲這個構建的容器設置/dev/shm分區的大小
1.7. configs
受權某個服務能夠訪問它下面配置的configs,支持兩種語法
1.7.1. 短語法
短語法只指定config名稱,受權容器能夠訪問config,並將其掛載到該容器下的/<config_name>
下面的例子受權redis服務訪問my_config和my_other_config配置。my_config的值設置的是./my_config.txt,而my_other_config的值指定的是外部資源,這就意味着該值已經被定義在Docker中了。
1.7.2. 長語法
長語法提供了更細粒度的控制
下面這個例子將在容器下設置my_config和redis_config,設置權限是0440,全部者和所屬組都是103,redis服務不能夠訪問my_other_config配置
1.8. container_name
自定義容器名稱,而不是用默認生成的名稱
1.9. depends_on
表示服務之間的依賴關係,服務依賴關係致使如下行爲:
下面的例子中,db和redis會先於web啓動,啓動web的時候也會建立並啓動db和redis,web中止以前會先中止db和redis
注意:depends_on不會等待db和redis啓動好了再啓動web
1.10. deploy
只有在集羣方式部署的時候這個配置纔有效
1.10.1. mode
global(每一個集羣節點只有一個容器) 或者 replicated (指定數量的容器)。默認是 replicated
1.11. env_file
添加一個環境變量文件,能夠是單個值或者一個列表
若是同一個變量出如今多個文件中,則後者覆蓋前者
1.12. environment
添加一個環境變量,能夠覆蓋env_file中同名的變量值
1.13. expose
在不將端口發佈到主機的狀況下公開端口
1.14. image
指定容器從哪一個鏡像啓動,能夠是鏡像ID,也能夠是鏡像tag
1.15. network_mode
網絡模式
1.16. ports
端口,兩種語法
短語法
長語法
1.17. restart
重啓策略,默認是no
1.18. ulimits
覆蓋容器默認的ulimits
1.19. volumes
掛載主機的路徑或volumes名稱
你能夠爲單個服務掛載一個主機路徑,這個時候就沒有定義頂級的volumes了。可是,若是你但願多個服務複用一個volumes,那麼這個時候就要定義在頂級了。
短語法
指定主機上的路徑(HOST:CONTAINER),或者一個訪問模式(HOST:CONTAINER:ro)
(PS:稍微解釋一下,好比/opt/data:/var/lib/mysql表示掛載到主機的路徑是/opt/data,掛載到容器的路徑是/var/lib/mysql,其實掛載能夠理解爲映射)
長語法
1.20. 指定時長與字節值
時長支持的單位:us,ms,s,m,h
字節大小支持的單位:b,k,m,g 或者 b,kb,mb,gb
2. Volume configuration
下面的例子展現了兩個服務,一個數據庫的數據目錄以一個volumn的形式與另外一個服務共享,以致於它能夠週期性的備份數據:
頂級volumns能夠是空的,此時它使用Docker引擎默認提供的驅動(大多數狀況下是local)來配置。你也能夠指定下列key
3. 示例
4. 參考文檔