使用PowerShell时,Docker将图像保存为两倍大小 - 保存原始字节流

N'u*_*urk 9 powershell cmd io-redirection docker

Docker版本18.03.1-ce,build 9ee9f40

我正在使用PowerShell在Windows上构建一个大项目.

发出命令时

docker save docker.elastic.co/kibana/kibana > deploy/kibana.docker
Run Code Online (Sandbox Code Playgroud)

我得到一个文件1.4Gb.

在CMD中运行的相同命令产生799Mb图像.

在bash中运行的相同命令产生799Mb图像.

CMD和Bash只需不到一分钟的时间来保存图像,而Powershell大约需要10分钟.

我无法在docker或MS docs中找到这种现象的正常解释.

现在"解决方案"是

Write-Output "Saving images to files"
cmd /c .\deploy-hack.cmd
Run Code Online (Sandbox Code Playgroud)

但我想找到实际的根本原因.

mkl*_*nt0 9

PowerShell不支持输出/传递原始字节流通过 -从外部程序的任何输出例如docker解析逐行,进和串然后输出到文件中重新编码(如果需要).
解析,解码和重新编码的开销解释了性能下降.

Windows PowerShell的>重定向运算符默认生成UTF16-LE("Unicode")文件(而PowerShell Core使用UTF8),即每个字符使用(至少)2个字节的文件.因此,它生成的文件大小是原始字节输入[1]的两倍,因为每个字节都被解释为在输出中接收2字节表示的字符.

最好的办法是使用docker save-o/ --output选项来指定输出文件(见的文档):

docker save docker.elastic.co/kibana/kibana -o deploy/kibana.docker
Run Code Online (Sandbox Code Playgroud)

[1]严格地说,PowerShell如何解释外部程序的输出取决于其值[console]::OutputEncoding,如果设置为UTF8(chcp 65001在Windows上),则可以将多个字节作为单个字符进行情境解释.但是,在Windows PowerShell上,默认值由(旧)系统区域设置的OEM代码页确定,该代码页始终为单字节编码.