使用本地文件在 Windows 上构建 docker 图像时使用 --squash 的替代方法
Alternative to using --squash when building docker images on Windows using local files
我们有一些用于构建 docker 图像的本地安装程序和 zip 文件。很容易让它在 Dockerfile 中工作:
FROM mcr.microsoft.com/windows/nanoserver
COPY myinstaller.exe .
RUN myinstaller.exe; \
del myinstaller.exe
这里的问题是它为 COPY 行生成了一层,这增加了图像的大小。一个常见的解决方法是使用 运行 行,从 Internet 下载文件,运行s 命令,然后删除安装文件。如上所述,问题是安装程序在本地文件系统上。
我发现 docker 有一个 --squash 命令:
docker build --squash -t mytestimage .
这正是我想要的:它给我一个没有这个不必要的额外安装程序文件的图像。要 运行 此命令,您需要启用实验性功能。还有一个未解决的问题可以简单地删除此功能:
https://github.com/moby/moby/issues/34565
在 Windows 上 运行 时,是否有其他方法可以在 Dockerfile 中使用本地安装程序,而不涉及设置服务器来提供文件?
我们最终设置 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
选项卡并单击 "Share"。使用小下拉菜单和 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: =%
是去掉字符串开头的一个space。
然后我们将要使用的 IP 地址存储在 hostip
中。我们在 net use
命令中使用它,它将 O:\
映射到 IP hostip
机器上的共享文件夹 vms
。我们使用用户名 share
和密码 password1
。请注意,这是一种非常糟糕的密码处理方式,因为它们应该是保密的!
有了这样的批处理文件,我们可以这样设置一个Docker文件:
# 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
以查看它是否有效,所以只需更改该行即可。
我还是建议大家搭建一个小的网络服务器,比如nginx
,用标准的方式写Docker文件,下载文件和运行在相同的 RUN
命令中使用它。这就是人们在看到 Docker 文件时所期望的,它应该是一个更强大的解决方案。
我们也希望Docker人要么做一个COPY
可以复制的命令,运行,删除同层的安装程序,要么--squash
正确执行。
我们有一些用于构建 docker 图像的本地安装程序和 zip 文件。很容易让它在 Dockerfile 中工作:
FROM mcr.microsoft.com/windows/nanoserver
COPY myinstaller.exe .
RUN myinstaller.exe; \
del myinstaller.exe
这里的问题是它为 COPY 行生成了一层,这增加了图像的大小。一个常见的解决方法是使用 运行 行,从 Internet 下载文件,运行s 命令,然后删除安装文件。如上所述,问题是安装程序在本地文件系统上。
我发现 docker 有一个 --squash 命令:
docker build --squash -t mytestimage .
这正是我想要的:它给我一个没有这个不必要的额外安装程序文件的图像。要 运行 此命令,您需要启用实验性功能。还有一个未解决的问题可以简单地删除此功能:
https://github.com/moby/moby/issues/34565
在 Windows 上 运行 时,是否有其他方法可以在 Dockerfile 中使用本地安装程序,而不涉及设置服务器来提供文件?
我们最终设置 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
选项卡并单击 "Share"。使用小下拉菜单和 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: =%
是去掉字符串开头的一个space。
然后我们将要使用的 IP 地址存储在 hostip
中。我们在 net use
命令中使用它,它将 O:\
映射到 IP hostip
机器上的共享文件夹 vms
。我们使用用户名 share
和密码 password1
。请注意,这是一种非常糟糕的密码处理方式,因为它们应该是保密的!
有了这样的批处理文件,我们可以这样设置一个Docker文件:
# 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
以查看它是否有效,所以只需更改该行即可。
我还是建议大家搭建一个小的网络服务器,比如nginx
,用标准的方式写Docker文件,下载文件和运行在相同的 RUN
命令中使用它。这就是人们在看到 Docker 文件时所期望的,它应该是一个更强大的解决方案。
我们也希望Docker人要么做一个COPY
可以复制的命令,运行,删除同层的安装程序,要么--squash
正确执行。