无法在Windows Docker容器中运行Cygwin

13

我一直在使用Docker for Windows,尝试创建一个Windows容器,在其中运行cygwin作为容器本身的shell。到目前为止,我还没有成功。以下是我一直在尝试的Dockerfile。

# escape=`
FROM microsoft/windowsservercore

SHELL ["powershell", "-command"]

RUN Invoke-WebRequest https://chocolatey.org/install.ps1 -UseBasicParsing | Invoke-Expression
RUN choco install cygwin -y
RUN refreshenv
RUN [Environment]::SetEnvironmentVariable('Path', $env:Path + ';C:\tools\cygwin\bin', [EnvironmentVariableTarget]::Machine)

我尝试通过设置ENTRYPOINT和CMD来进入cygwin,但两者似乎都没有起作用。我也使用 docker run -it 进入了容器,并触发cygwin命令以进入shell,但似乎没有任何反应。我没有收到错误提示,它只是返回命令提示符,就好像什么都没有发生一样。

在Windows容器中运行另一个shell是否可能,或者我只是做错了什么?

谢谢!


1
似乎有一整类二进制文件无法在Windows Docker容器中运行(默默退出)。Cygwin二进制文件就是一个例子。64位不是问题,因为它在nanoserver和windowsservercore上都会发生。如果有人知道情况,请留言。 - Akom
@Akom,这个问题有什么想法/进展吗?我也遇到了同样的问题,容器总是崩溃。 - Żubrówka
我将在此问题上设置赏金,因为这是一个需要解决的重要话题 - 在DevOps环境中非常相关。 - Żubrówka
@Żubrówka 我已经编辑了我的回答:没有确切的进展,除了可能的解决方法。 - VonC
@Żubrówka,我没有看到容器崩溃,而是可执行文件无法在容器中运行。我在这方面一无所获。我看到了一些类似症状的票据,但没有找到解释。 - Akom
检查一下我的答案,我成功让事情为我工作。 - Żubrówka
3个回答

3
您不会使用docker run“连接”到容器:您将使用它来启动容器。
在您的情况下,如此处所示,docker run -it是正确的方法。
您可以尝试使用c:\cygwin\bin\bash作为入口点,如这个问题中所示。
如在问题32330中所述:

别误会,cygwin应该可以在Docker Windows容器中工作。

但是,这也有点自相矛盾,容器在Windows上费尽心血模仿了Linux上的容器,只为让人们想在这些新的Docker Windows容器中运行Linux-utils...

同一问题仍未解决,新案例在2018年5月和6月出现:

我们拥有一个使用Visual Studio编译的环境,但是我们仍然希望使用git和一些从linux中获取的非常有用的命令。
此外,我们使用现成的实用程序(例如git-repo)使用linux命令(例如curl、grep等)

一些构建需要Cygwin,例如ICU(跨平台基于Unicode的全球化库),最糟糕的是:我们的构建需要从源代码构建。


您可以在MSYS2-packages问题1239中看到崩溃的示例。
Step 5/5 : RUN "C:\\msys64\\usr\\bin\\ls.exe"
 ---> Running in 5d7867a1f8da
The command 'cmd /S /C "C:\\msys64\\usr\\bin\\ls.exe"' returned a non-zero code: 3221225794

这可以获取有关崩溃的更多信息:
PS C:\msys64\usr\bin> 
  Get-EventLog -Index 28,29,30 -LogName "Application" | Format-List -Property *

"解决方法是:

使用妥善的处理方式

"
PS > xcopy /S C:\Git C:\Git_Copy
PS > C:\Git_Copy\usr\bin\sh.exe --version > v.txt
PS > type v.txt

正如该线程中提到的,输出结果会在容器中丢失,因此将其发送到文本文件中。

3
经过长时间的尝试,我得出以下结论:
  • 如果您的Cygwin工具导致容器崩溃,您需要使用进程隔离。请参见https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility了解要求(基本上您需要使用Windows Server 2016和一个匹配的Docker镜像版本)。我花了一些时间试图理解为什么Hyper-V隔离不起作用,但到目前为止我没有得出任何结论;

  • 如果您的Cygwin工具似乎没有反应 - 但它们不会导致容器崩溃 - 您需要删除-t标志(-i标志仍然可以使用)或者尝试重定向stdout。显然,当MSYS2处理某些伪tty时存在问题。您可以通过将stdout重定向到文件来验证程序是否仍在运行(例如,如果您在没有任何stdout重定向的情况下运行whoami,则不会输出任何内容,但是whoami> out.txt将向文件输出预期结果)。可能可以通过替换伪tty来修复此问题,但我没有尝试过。我怀疑问题出在MSYS2库中的无效句柄上 - 因为其他控制台应用程序可以将内容打印到终端 - 但我没有进行验证。

希望这能对所有遇到相同问题的人有所帮助。

有趣的设置,比我的答案更精确。+1 - VonC

2
我成功地将一个预安装的(从主机复制)Cygwin副本在nanoserver-based容器中运行,只需以下两个步骤:
  1. 在交互式运行docker时,在docker run cmd-line中使用Żubrówka的建议,即不要使用-t
  2. 将主机(Windows Server 2016)的kernel32.dll复制到容器的c:\windows\system32中
我在我的系统上找到了几个版本的kernel32.dll,并使用了md5哈希值为d8948a7af764f7153b3e396ad44992ff的c:\windows\system32中的版本。
这也使得许多其他可执行文件可以正常工作。请注意,如果没有tty,则使用容器会更加麻烦,bash shell也无法呈现提示符。然而,依赖于cygwin组件的脚本(在我的情况下是通过Jenkins)可以正常工作。
如果这些步骤无法解决问题,请尝试此指南,它对我很有帮助。如果您的Windows应用程序(除Cygwin外)确实缺少DLL,则此指南中的说明可以提供帮助。我从未想过SysInternals的procmon.exe可以在主机上运行并仍然报告来自容器的事件!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接