命令是 运行 在上一个完成之前

Command is run before the previous one is finished

考虑以下 Dockerfile。它尝试通过在单个 RUN 命令中下载、安装然后删除安装程序来安装 Visual Studio Build Tools。

FROM mcr.microsoft.com/windows/servercore:ltsc2022

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]

RUN Invoke-WebRequest \
        -Uri https://aka.ms/vs/17/release/vs_buildtools.exe \
        -OutFile vs_buildtools.exe; \
    .\vs_buildtools.exe --nocache --norestart --quiet --wait \
        --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \
        --add Microsoft.VisualStudio.Component.Windows10SDK.19041; \
    Remove-Item -Path vs_buildtools.exe

构建映像时,下载并启动安装程序,然后在安装完成之前尝试删除安装程序!这当然会产生一个错误:

Remove-Item : Cannot remove item C:\vs_buildtools.exe: The process cannot
access the file 'C:\vs_buildtools.exe' because it is being used by another
process.

出错后继续构建,完成安装。

为什么 Remove-Item.\vs_buildtools.exe 完成之前执行?

如果我将 Remove-Item 取出到它自己的 RUN 命令中,它工作正常:

RUN Invoke-WebRequest \
        -Uri https://aka.ms/vs/17/release/vs_buildtools.exe \
        -OutFile vs_buildtools.exe; \
    .\vs_buildtools.exe --nocache --norestart --quiet --wait \
        --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \
        --add Microsoft.VisualStudio.Component.Windows10SDK.19041
RUN Remove-Item -Path vs_buildtools.exe

解决方法是使用 cmd 而不是 powershell

以下两种方法都有效:

RUN Invoke-WebRequest \
        -Uri https://aka.ms/vs/17/release/vs_buildtools.exe \
        -OutFile vs_buildtools.exe; \
    cmd /c "vs_buildtools.exe --nocache --norestart --quiet --wait \
        --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \
        --add Microsoft.VisualStudio.Component.Windows10SDK.19041"; \
    Remove-Item -Path vs_buildtools.exe
SHELL ["cmd", "/S", "/C"]
RUN curl -SL https://aka.ms/vs/17/release/vs_buildtools.exe -o vs_buildtools.exe \
    && call vs_buildtools.exe --nocache --norestart --quiet --wait \
        --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 \
        --add Microsoft.VisualStudio.Component.Windows10SDK.19041 \
    && call del /q vs_buildtools.exe
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';"]