在有了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中使用的基础镜像便可。