使用本地文件在Windows上构建Docker映像时替代使用--squash

时间:2019-03-18 11:42:11

标签: docker dockerfile docker-windows

---更新---

-squash在Windows上似乎已出错,因此实际上不是一个选择: https://github.com/moby/moby/issues/31468

---结束更新---

我们有一些本地安装程序和zip文件,用于构建docker映像。很容易在Dockerfile中使用它:

FROM mcr.microsoft.com/windows/nanoserver

COPY myinstaller.exe .
RUN myinstaller.exe; \
    del myinstaller.exe

这里的问题是,它会为COPY行生成一个图层,这会增加图像的大小。常见的解决方法是只有一条RUN行,该行从Internet下载文件,运行命令,然后删除安装文件。如上所述,问题是安装程序位于本地文件系统上。

我发现docker有一个--squash命令:

docker build --squash -t mytestimage .

这正是我想要的:它为我提供了一个不需要此多余安装程序文件的映像。要运行此命令,您需要启用实验功能。简单删除此功能还有一个未解决的问题:

https://github.com/moby/moby/issues/34565

在Windows上运行时,是否有其他方法可以在Dockerfile中使用本地安装程序,而无需设置服务器来提供文件?

1 个答案:

答案 0 :(得分:1)

我们最终建立了nginx,以便在构建时提供文件。在我们的构建服务器上,构建我们的docker映像的机器与具有安装程序文件的服务器之间具有很好的连接,因此下载大文件并不是一个真正的问题。

关于--squash,它在Windows上已被Docker窃听。这是相关的问题:

https://github.com/moby/moby/issues/31468

--squash移出实验阶段是有问题的,但似乎没有太多支持:

https://github.com/moby/moby/issues/38657

有些人提出的替代--squash的替代方案是多阶段构建,请在此处进行讨论:

https://github.com/moby/moby/issues/34565

--squash之外还有另一种选择,如果您具有本地安装程序文件,则不想设置Web服务器,并且希望docker映像较小,并且您正在运行Windows:使用映射的驱动器。

在Windows中,您可以与网络上的其他用户共享文件夹。 Docker容器就像在您的物理机上运行的另一台计算机一样,它可以访问这些网络驱动器。

首先设置一个新用户,例如用户名share和密码password1。在计算机上的某个位置创建一个文件夹。然后右键单击它,单击properties,然后转到Sharing选项卡并单击“共享”。使用小下拉菜单和Find people ...查找刚刚创建的用户,并与该用户共享文件夹。

为测试项目在某处创建一个文件夹。创建一个如下所示的批处理文件setupshare.bat

@echo off
for /f "tokens=2 delims=:" %%i in ('ipconfig ^| findstr "Default Gateway"') do (
    set hostip=%%i
    goto :end
)
:end
set hostip=%hostip: =%
net use O: \\%hostip%\vms /USER:share password1

该文件的第一部分只是找到docker容器可用于访问其主机的IP地址。这不是我整理过的最漂亮的东西,所以请告诉我是否有更好的方法!

它使用for循环,因为这是将命令输出保存到批处理文件中的变量的方法。该命令是ipconfig,我们将其通过管道传递到findstr并搜索Default Gateway。我们需要使用^|而不是|,因为它处于for循环中。 for循环的第一部分从定界符上的命令中划分出每一行,在本例中为:,而我们仅采用第二个标记。如果有多个带有默认网关的条目,则for循环仅处理第一行。如果有多个条目,而第一个不是正确的条目,则此脚本不起作用。

set hostip=%hostip: =%行用于删除字符串开头的空格。

然后我们将要使用的IP地址存储在hostip中。我们在net use命令中使用此命令,该命令会将O:\映射到IP为vms的计算机上的共享文件夹hostip。我们使用用户名share和密码password1。请注意,这是处理密码的非常不好的方法,因为它们应该是秘密的!

使用这样的批处理文件,我们可以通过以下方式设置Dockerfile:

# escape=`
FROM mcr.microsoft.com/dotnet/core/sdk:3.0

COPY setupshare.bat .

RUN setupshare.bat && `
    copy O:\file.txt file.txt

RUN命令将首先调用setupshare.bat,以正确设置网络共享。然后,我们可以使用共享的任何文件(例如,大型安装程序)安装所需的东西。在这种情况下,我仅共享一个测试文件file.txt来查看它是否有效,因此只需更改该行即可。

我仍然建议每个人都设置一个小型Web服务器,例如nginx,并使用编写Dockerfile的标准方式,并使用相同的RUN命令下载文件并运行它。这就是人们看到Dockerfile时的期望,它应该是一个更强大的解决方案。

我们还希望Docker人员能够执行COPY命令来复制,运行和删除同一层中的安装程序,或者希望--squash得到正确实施。