Windows Containers 大冒险: 出行计划(Dockerfile)

前言

在有了Docker相关的基础知识后,就能够开始指定出行计划了(Dockerfile),计划里将记录咱们的出发点(FROM),须要购买的物品(COPY/ADD),在预约的景点拍照(RUN)。固然自己Dockerfile其实也能够在被发明的那个时候称为Recipe的,只是这个单词在计算机领域被用到太普遍了,没有Dockerfile来得特立独行。下面就来简单说说Dockerfile.git

Dockerfile简介

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

clipboard.png

ENTRYPOINT 指令

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及转义符号

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

相关文章
相关标签/搜索