构建Windows Docker镜像失败求助:PowerShell命令报错0x2
问题背景
尝试构建包含JDK与Android开发环境的Windows Docker镜像,使用的Dockerfile如下:
# Use a Windows base image FROM mcr.microsoft.com/windows/servercore:ltsc2022 # Set environment variables ENV ANDROID_HOME="C:/android-sdk" ENV PATH="C:/android-sdk/platform-tools;C:/android-sdk/cmdline-tools/latest/bin;C:/android-sdk/emulator;C:/android-sdk/tools;C:/android-sdk/tools/bin;%PATH%" # Set working directory WORKDIR C:/ # Use PowerShell as the default shell SHELL ["powershell", "-Command"] # Download JDK RUN Invoke-WebRequest -Uri "https://download.oracle.com/java/23/latest/jdk-23_windows-x64_bin.zip" -OutFile "C:/jdk.zip" # Extract JDK RUN Expand-Archive -Path "C:/jdk.zip" -DestinationPath "C:/jdk" -Force # Remove JDK zip after extraction RUN Remove-Item -Path "C:/jdk.zip" # Set JAVA_HOME environment variable ENV JAVA_HOME="C:/jdk" ENV PATH="C:/jdk/bin;%PATH%" # Download Android command-line tools RUN Invoke-WebRequest -Uri "https://dl.google.com/android/repository/commandlinetools-win-11076708_latest.zip" -OutFile "C:/commandlinetools.zip" # Extract Android command-line tools RUN Expand-Archive -Path "C:/commandlinetools.zip" -DestinationPath "C:/android-sdk" -Force # Remove command-line tools zip after extraction RUN Remove-Item -Path "C:/commandlinetools.zip" # Accept Android SDK licenses RUN echo y | & "C:/android-sdk/cmdline-tools/latest/bin/sdkmanager.bat" --licenses" # Install necessary Android SDK packages RUN & "C:/android-sdk/cmdline-tools/latest/bin/sdkmanager.bat" "platform-tools" "platforms;android-34" "build-tools;34.0.0" "emulator" # Final environment settings ENV JAVA_HOME="C:/jdk" ENV PATH="C:/jdk/bin;%PATH%"
执行命令 docker build --no-cache -t android-windows . 时,在下载JDK的RUN步骤报错,错误信息:
Step 6/17 : RUN Invoke-WebRequest -Uri "https://download.oracle.com/java/23/latest/jdk-23_windows-x64_bin.zip" -OutFile "C:/jdk.zip" ---> Running in 325a4570f52c container 325a4570f52c8362c42afae28526f8227ce277de6a9dc5b98b91e6dafe90e405 encountered an error during hcs::System::CreateProcess: powershell -Command Invoke-WebRequest -Uri "https://download.oracle.com/java/23/latest/jdk-23_windows-x64_bin.zip" -OutFile "C:/jdk.zip": failure in a Windows system call: The system cannot find the file specified. (0x2) [Event Detail: Provider: 00000000-0000-0000-0000-000000000000] [Event Detail: Provider: 00000000-0000-0000-0000-000000000000] [Event Detail: onecore\vm\compute\management\orchestration\vmhostedcontainer\processmanagement.cpp(173)\vmcomputeagent.exe!00007FF66CC0014D: (caller: 00007FF66CBA4C97) Exception(2) tid(3d4) 80070002 The system cannot find the file specified. CallContext:[\Bridge_ProcessMessage\VmHostedContainer_ExecuteProcess] Provider: 00000000-0000-0000-0000-000000000000]
已配置Docker Desktop为Windows容器模式,启用Windows功能中的Containers和Hyper-V,尝试修改输出路径为C://jdk.zip和C:\jdk.zip,问题依旧。
解决方案
1. 修正PowerShell的Shell路径配置
Windows Server Core镜像中,PowerShell的完整路径为C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,原SHELL指令仅写powershell可能导致系统无法找到可执行文件。修改SHELL指令:
SHELL ["C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", "-Command", "$ErrorActionPreference = 'Stop';"]
添加$ErrorActionPreference = 'Stop'可让脚本在出错时立即终止,便于排查问题。
2. 替换JDK下载链接(解决Oracle登录限制)
Oracle的JDK官方下载链接需要登录验证,容器内无法完成登录流程导致下载失败。改用无需登录的OpenJDK镜像链接,比如Adoptium提供的OpenJDK 23:
# Download JDK(替换为OpenJDK链接) RUN Invoke-WebRequest -Uri "https://github.com/adoptium/temurin23-binaries/releases/download/jdk-23%2B37/OpenJDK23U-jdk_x64_windows_hotspot_23_37.zip" -OutFile "C:/jdk.zip"
3. 合并RUN指令减少容器启动次数
将JDK下载、解压、删除压缩包的步骤合并为一个RUN指令,减少容器启动次数,避免中间步骤的路径或权限问题:
# Download, extract and clean up JDK RUN Invoke-WebRequest -Uri "https://github.com/adoptium/temurin23-binaries/releases/download/jdk-23%2B37/OpenJDK23U-jdk_x64_windows_hotspot_23_37.zip" -OutFile "C:/jdk.zip"; ` Expand-Archive -Path "C:/jdk.zip" -DestinationPath "C:/jdk" -Force; ` Remove-Item -Path "C:/jdk.zip" -Force
注意使用反引号 分隔多行命令(PowerShell的换行符)。
4. 提前验证容器内基础命令可用性
在下载JDK前添加测试指令,验证PowerShell和Invoke-WebRequest是否正常工作:
# Test PowerShell and network connectivity RUN Invoke-WebRequest -Uri "https://www.google.com" -OutFile "C:/test.html"; ` Remove-Item -Path "C:/test.html" -Force
如果这一步报错,说明容器网络或PowerShell环境存在问题,需先排查网络连接或镜像完整性。
5. 修复Android许可证验证的语法错误
原Dockerfile中接受许可证的RUN指令有语法错误(末尾多了一个双引号),修正为:
# Accept Android SDK licenses RUN echo y | & "C:/android-sdk/cmdline-tools/latest/bin/sdkmanager.bat" --licenses
内容的提问来源于stack exchange,提问作者MrJay

