.NET 8.0+Playwright+NUnit Docker部署:Chromium可执行文件缺失求助
问题描述
我正在开发基于.NET 8.0、C#、NUnit测试框架和Playwright的测试项目,编写了如下Dockerfile:
# Use an official .NET 8.0 SDK base image FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env # Set the working directory to /app WORKDIR /app # Copy csproj and restore NuGet packages COPY *.sln ./ COPY EncryptionDecryptionUsingSymmetricKey/EncryptionDecryptionUsingSymmetricKey.csproj EncryptionDecryptionUsingSymmetricKey/ COPY MyTestProject/MyTestProject.csproj MyTestProject/ RUN dotnet restore #Installing Playwright Separately RUN rm -rf /root/.cache/ms-playwright RUN apt-get update && apt-get install -y chromium ENV CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser RUN apt-get update RUN apt-get -y install curl gnupg RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - RUN apt-get -y install nodejs RUN npm install playwright ENV CHROMIUM_EXECUTABLE_PATH=/root/.cache/ms-playwright/chromium-1117/chrome-linux/chrome RUN export PWADIR=/root/.cache/ms-playwright/chromium-1117/chrome-linux/chrome RUN echo "Chromium Executable Path: $CHROMIUM_EXECUTABLE_PATH" # Verify the Chromium executable path RUN apt-get update && apt-get install -y --no-install-recommends \ fonts-liberation\ libasound2\ libatk-bridge2.0-0\ libatk1.0-0\ libatspi2.0-0\ libcairo2\ libcups2\ libdbus-1-3\ libdrm2\ libgbm1\ libglib2.0-0\ libgtk-3-0\ libnspr4\ libnss3\ libpango-1.0-0\ libx11-6\ libxcb1\ libxcomposite1\ libxdamage1\ libxext6\ libxfixes3\ libxrandr2 # Copy the rest of the application code COPY . . # Install NUnit and Microsoft.Playwright.NUnit NuGet packages RUN dotnet add MyTestProject package NUnit --version 3.14.0 RUN dotnet add MyTestProject package Microsoft.Playwright.NUnit --version 1.44.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration.Abstractions --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration.Json --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.NET.Test.Sdk --version 17.8.0 RUN dotnet add MyTestProject package NUnit.Analyzers --version 3.9.0 RUN dotnet add MyTestProject package NUnit3TestAdapter --version 4.5.0 RUN dotnet add MyTestProject package Allure.NUnit --version 2.12.1 RUN dotnet add MyTestProject package coverlet.collector --version 6.0.0 # Build the application RUN dotnet build # Installing browser msedge RUN dotnet tool update --global PowerShell #RUN apt-get update && apt-get install -y microsoft-edge-dev #RUN echo $PATH | grep -q '/usr/bin/microsoft-edge-dev' || (echo "Error: Microsoft Edge not found in PATH" && exit 1) # Set the environment variable to point to the Microsoft Edge binary for Playwright ENV PLAYWRIGHT_BROWSERS_PATH=/usr/bin/microsoft-edge-dev #Installing Playwright using playwright.ps1 RUN pwsh /app/MyTestProject/bin/Debug/net8.0/playwright.ps1 install RUN pwsh /app/MyTestProject/bin/Debug/net8.0/playwright.ps1 install-deps chromium RUN dotnet publish MyTestProject/MyTestProject.csproj -c Release -o out #Runtime FROM mcr.microsoft.com/dotnet/sdk:8.0 # Set the working directory inside the container WORKDIR /app # Copy the built application from the build stage into this stage COPY --from=build-env /app/out . # Execute the tests ENTRYPOINT ["dotnet", "test", "MyTestProject.dll", "--settings:Runset.runsettings"]
构建后运行测试时出现如下错误:
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Failed LogInInfo(MyTestProject.Assets.QA.TestsData.TestDataObj.Login) [649 ms] Error Message: Microsoft.Playwright.PlaywrightException : Executable doesn't exist at /root/.cache/ms-playwright/chromium-1117/chrome-linux/chrome ╔════════════════════════════════════════════════════════════╗ ║ Looks like Playwright was just installed or updated. ║ ║ Please run the following command to download new browsers: ║ ║ ║ ║ pwsh bin/Debug/netX/playwright.ps1 install ║ ║ ║ ║ <3 Playwright Team ║ ╚════════════════════════════════════════════════════════════╝ Stack Trace: at Microsoft.Playwright.Transport.Connection.InnerSendMessageToServerAsync[T](ChannelOwner object, String method, Dictionary`2 dictionary, Boolean keepNulls) in /_/src/Playwright/Transport/Connection.cs:line 206 at Microsoft.Playwright.Transport.Connection.WrapApiCallAsync[T](Func`1 action, Boolean isInternal) in /_/src/Playwright/Transport/Connection.cs:line 532 at Microsoft.Playwright.Core.BrowserType.LaunchAsync(BrowserTypeLaunchOptions options) in /_/src/Playwright/Core/BrowserType.cs:line 56 at Microsoft.Playwright.NUnit.BrowserService.CreateBrowser(IBrowserType browserType) in /_/src/Playwright.NUnit/BrowserService.cs:line 55 at Microsoft.Playwright.NUnit.BrowserService.<>c__DisplayClass5_0.<Register>b__0>d.MoveNext() in /_/src/Playwright.NUnit/BrowserService.cs:line 45 --- End of stack trace from previous location --- at Microsoft.Playwright.NUnit.WorkerAwareTest.RegisterService[T](String name, Func`1 factory) in /_/src/Playwright.NUnit/WorkerAwareTest.cs:line 55 at Microsoft.Playwright.NUnit.BrowserTest.BrowserSetup() in /_/src/Playwright.NUnit/BrowserTest.cs:line 46 at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted() at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter) at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke) at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunSetUpOrTearDownMethod(TestExecutionContext context, IMethodInfo method) at NUnit.Framework.Internal.Commands.SetUpTearDownItem.RunSetUp(TestExecutionContext context) at NUnit.Framework.Internal.Commands.SetUpTearDownCommand.<>c__DisplayClass0_0.<.ctor>b__0(TestExecutionContext context) at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0() at NUnit.Framework.Internal.Commands.DelegatingTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
检查镜像后发现没有/root/.cache目录,不清楚问题出在哪。
问题排查与修复方案
核心问题分析
- 多阶段构建上下文丢失:
build-env阶段中通过playwright.ps1 install下载的浏览器缓存(/root/.cache/ms-playwright)没有被复制到最终的runtime阶段,runtime阶段是全新的镜像,仅复制了发布后的out目录,导致Playwright找不到浏览器可执行文件。 - 重复安装导致路径冲突:同时用
npm install playwright和.NET的playwright.ps1安装Playwright,两种方式的浏览器存储路径不同,后续设置的CHROMIUM_EXECUTABLE_PATH指向了npm安装的路径,但实际运行时依赖的是.NET版的浏览器路径。 - 环境变量设置混乱且未传递:
CHROMIUM_EXECUTABLE_PATH和PLAYWRIGHT_BROWSERS_PATH多次修改,且未将关键环境变量传递到runtime阶段,Playwright无法正确识别浏览器位置。 - 冗余依赖安装:安装nodejs和npm完全不必要,.NET版Playwright自带工具链,不需要依赖Node环境。
修复后的Dockerfile
# 构建阶段:使用.NET 8 SDK镜像 FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-env WORKDIR /app # 复制项目文件并还原依赖 COPY *.sln ./ COPY EncryptionDecryptionUsingSymmetricKey/EncryptionDecryptionUsingSymmetricKey.csproj EncryptionDecryptionUsingSymmetricKey/ COPY MyTestProject/MyTestProject.csproj MyTestProject/ RUN dotnet restore # 复制所有代码 COPY . . # 安装测试依赖(建议直接在项目csproj中配置,而非在Dockerfile中添加) RUN dotnet add MyTestProject package NUnit --version 3.14.0 RUN dotnet add MyTestProject package Microsoft.Playwright.NUnit --version 1.44.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration.Abstractions --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.Extensions.Configuration.Json --version 8.0.0 RUN dotnet add MyTestProject package Microsoft.NET.Test.Sdk --version 17.8.0 RUN dotnet add MyTestProject package NUnit.Analyzers --version 3.9.0 RUN dotnet add MyTestProject package NUnit3TestAdapter --version 4.5.0 RUN dotnet add MyTestProject package Allure.NUnit --version 2.12.1 RUN dotnet add MyTestProject package coverlet.collector --version 6.0.0 # 构建项目 RUN dotnet build # 安装Playwright浏览器及依赖(使用.NET官方工具,无需Node) RUN dotnet tool install --global Microsoft.Playwright.CLI ENV PATH="$PATH:/root/.dotnet/tools" RUN playwright install chromium RUN playwright install-deps chromium # 发布测试项目 RUN dotnet publish MyTestProject/MyTestProject.csproj -c Release -o out # 运行阶段:复用SDK镜像(或改用runtime镜像,需确保包含测试依赖) FROM mcr.microsoft.com/dotnet/sdk:8.0 WORKDIR /app # 复制发布文件和Playwright浏览器缓存 COPY --from=build-env /app/out . COPY --from=build-env /root/.cache/ms-playwright /root/.cache/ms-playwright # 设置环境变量,指定浏览器路径(可选,Playwright默认会读取缓存路径) ENV PLAYWRIGHT_BROWSERS_PATH=/root/.cache/ms-playwright # 执行测试 ENTRYPOINT ["dotnet", "test", "MyTestProject.dll", "--settings:Runset.runsettings"]
关键修复点说明
- 移除Node.js/npm依赖:完全删除nodejs、curl、gnupg等不必要的安装步骤,改用.NET官方的
Microsoft.Playwright.CLI工具安装浏览器。 - 复制浏览器缓存到runtime阶段:新增
COPY --from=build-env /root/.cache/ms-playwright /root/.cache/ms-playwright命令,将构建阶段下载的浏览器文件同步到最终镜像。 - 统一Playwright安装方式:使用
playwright install chromium命令,确保浏览器存储在Playwright默认的缓存路径中,无需手动设置CHROMIUM_EXECUTABLE_PATH。 - 传递必要环境变量:将
PLAYWRIGHT_BROWSERS_PATH设置为缓存路径,确保Playwright能正确找到浏览器。
额外优化建议
- 将所有NuGet依赖直接配置在
MyTestProject.csproj文件中,避免在Dockerfile中重复执行dotnet add package命令,提升构建效率和可维护性。 - 如果不需要在运行阶段保留SDK,可以改用
mcr.microsoft.com/dotnet/runtime:8.0作为基础镜像,但需额外安装测试运行时依赖(如dotnet-runtime-deps和测试工具)。
内容的提问来源于stack exchange,提问作者Kedar Ghadge
相关产品推荐
相关产品推荐

