在有了Docker相關的基礎知識後,就能夠開始指定出行計劃了(Dockerfile),計劃裏將記錄咱們的出發點(FROM),須要購買的物品(COPY/ADD),在預約的景點拍照(RUN)。固然自己Dockerfile其實也能夠在被髮明的那個時候稱爲Recipe的,只是這個單詞在計算機領域被用到太普遍了,沒有Dockerfile來得特立獨行。下面就來簡單說說Dockerfile.git
Dockerfile是用來構建鏡像的文本文件,其中記錄瞭如何構建鏡像的命令。按照最新的文檔,目前能夠在Dockerfile中使用FROM, RUN, CMD, LABEL, MAINTAINER, EXPOSE, ENV, ADD, COPY, ENTRYPOINT, VOLUME, USER, WORKDIR, ARG, ONBUILD, STOPSIGNAL, HEALTHCHECK, SHELL共18個指令。其中MAINTAINER已經不推薦使用,可使用LABEL替代。github
下面就是一個IIS鏡像的例子。這裏須要注意的是ENTRYPOINT指令中的使用的ServiceMonitor.exe, 這是專爲ENTRYPOINT設計的應用,目前已在Github上開源。docker
# escape=` FROM microsoft/windowsservercore:1709 RUN powershell -Command ` Add-WindowsFeature Web-Server; ` Invoke-WebRequest -UseBasicParsing -Uri "https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.3/ServiceMonitor.exe" -OutFile "C:\ServiceMonitor.exe" EXPOSE 80 ENTRYPOINT ["C:\\ServiceMonitor.exe", "w3svc"]
其中FROM指令用於指定在構建新鏡像時將使用的基礎鏡像, 通用用途的Windows容器通常能夠選擇則 microsoft/windowsservercore 或者 microsoft/nanoserver。若是鏡像是用來運行ASP.NET或者ASP.NET Core應用,那麼可使用 microsoft/aspnet 或者 microsoft/aspnetcore 鏡像。shell
接下來的RUN指令則是執行PowerShell的Invoke-WebRequest命令下載ServiceMonitor.exe應用。EXPOSE則是用來通知Docker當容器運行時監聽的端口。windows
在重點介紹ENTRYPOINT指令前,先來談談Dockerfile中的命令格式,直白的表達就是何時用中括號([])。在Docker的官方文檔說明中,使用中括號的被稱爲exec格式,反之則稱爲shell格式。二者的區別能夠用如下兩個Dockerfile來對比區分。一句話的解釋就是使用exec格式的話,將按照exec中指定的命令運行。使用shell格式化的話,將使用默認命令行執行。app
exec form工具
FROM microsoft/windowservercore:1709 RUN ["powershell", "New-Item", "c:/test"]
shell formui
FROM microsoft/windowservercore:1709 RUN powershell New-Item c:/test
ENTRYPOINT指令的做用是將容器配置成可執行程序,或者說設置默認執行的程序,而CMD指令只指定了程序默認執行時使用的參數。在Docker的官方文檔中有一張很是好的表格羅列各類狀況。現摘錄以下。spa
No ENTRYPOINT | ENTRYPOINT exec_entry 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_entry p1_entry exec_cmd p1_cmd |
CMD [「p1_cmd」, 「p2_cmd」] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | 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 | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
這張表格裏混合了好幾種狀況,能夠按照縱向列的方式來閱讀。當沒有指定ENTRYPOINT時,以CMD中指定的命令和參數爲準(第一列)。當ENTRYPOINT和CMD同時存在,且ENTRYPOINT以shell格式存在時,以ENTRYPOINT中指定的命令爲準(第二列)。當ENTRYPOINT和CMD同時存在,且都以exec格式存在,則合併ENTRYPOINT和CMD中指定的命令和參數。操作系統
PowerShell 首次出如今2006年,它的出現統一了Windows下命令行的設計方式,讓管理員和開發者可使用動詞-名詞的方式來使用開發命令行工具。PowerShell自己對標Linux的Python,做爲膠水語言來簡化操做系統的管理。固然Python目前比PowerShell仍是領先一些,Web應用開發的能力也是PowerShell所不具有的,這和PowerShell作爲管理員工具存在的初始定位有關。
那麼在Dockerfile中如何使用PowerShell呢?這裏以一個Dockerfile爲例進行說明。首先,經過escape註釋語句設置本Dockerfile中的轉義符號爲倒角符(`)。接下來經過SHELL指令設置容器內默認命令行爲PowerShell。而後經過RUN指令運行PowerShell命令。這裏須要注意的是,示例中運行的已經不是單行命令,而是腳本塊。所以命令之間是經過分號(;)進行分隔的。而爲了不一行命令過長,則使用倒角符截斷命令參數。
PowerShell若是要展開來討論,作爲開發語言也有不少要討論的地方,在Dockerfile中通常只是用來執行現成的命令。同時須要注意的在Windows Server, version 1709中PowerShell已從nanoserver鏡像中移除。
#escape=` FROM microsoft/windowsservercore SHELL [ "powershell", "-command" ] RUN $ErrorActionPreference = 'Stop'; ` $ProgressPreference = 'SilentlyContinue'; ` $null = New-Item -Path c:\apps -Type Directory RUN Invoke-WebRequest -Uri https://download.sysinternals.com/files/SysinternalsSuite.zip ` -UseBasicParsing -OutFile c:\apps\SysinternalsSuite.zip ` -Proxy http://192.168.0.124:1080; ` Expand-Archive -Path C:\apps\SysinternalsSuite.zip -DestinationPath C:\apps\sysinternals\ -Force; ` Remove-Item -Path c:\apps\SysinternalsSuite.zip ENTRYPOINT [ "powershell" ]
文章標題中使用了出行計劃來形容Dockerfile之於容器製做的做用。技術上來講Dockerfile的存在使得開發人員能夠在代碼庫中管理最終交付物的生成過程,好比若是應用要發佈到Windows Server, version 1803中,只需更改FROM中使用的基礎鏡像便可。