通过AWS CodePipeline部署EBS成功,但Startup.cs运行时出现错误
此前手动执行dotnet publish -r linux-x64 --self-contained true --output build,将build文件夹打包上传至Elastic Beanstalk控制台,应用可正常运行。改用AWS CodePipeline实现自动化部署后,部署流程成功完成,但EBS日志显示应用启动时抛出未处理异常。
配置文件
buildspec.yml
version: 0.2 phases: install: commands: - curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel STS # runtime-versions: # dotnet: 7.0 pre_build: commands: - dotnet restore Vepo.Web/Vepo.Web.csproj - dotnet restore Vepo.Services/Vepo.Services.csproj - dotnet restore Vepo.Infrastructure/Vepo.Infrastructure.csproj - dotnet restore Vepo.Domain/Vepo.Domain.csproj - dotnet restore Vepo.DataContext/Vepo.DataContext.csproj - dotnet restore Vepo.Data/Vepo.Data.csproj - dotnet restore Vepo.Common/Vepo.Common.csproj - dotnet restore Vepo.Application/Vepo.Application.csproj build: commands: - dotnet build -r linux-x64 --self-contained true Vepo.Web/Vepo.Web.csproj post_build: commands: - dotnet publish -r linux-x64 --self-contained true -c Release -o ./app/ Vepo.Web/Vepo.Web.csproj artifacts: files: - "**/*"
Procfile
web: dotnet ./app/Vepo.Web.dll
错误日志
Jul 31 01:22:14 ip-172-31-1-234 web: Unhandled exception.
System.Exception: Could not resolve a service of type 'Vepo.Infrastructure.IGroceryItmsSearchIndexService' for the parameter 'searchIndexService' of method 'Configure' on type 'Vepo.Web.Startup'.
Jul 31 01:22:14 ip-172-31-1-234 web: ---> System.ArgumentNullException: Value cannot be null. (Parameter 'uriString')
Jul 31 01:22:14 ip-172-31-1-234 web: at System.ArgumentNullException.Throw(String paramName)
Jul 31 01:22:14 ip-172-31-1-234 web: at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
Jul 31 01:22:14 ip-172-31-1-234 web: at System.Uri..ctor(String uriString)
Jul 31 01:22:14 ip-172-31-1-234 web: at Vepo.Infrastructure.SearchService..ctor(String uri, String username, String password, String defaultIndex, Boolean forceInMemory, Boolean refreshOnUpdate) in /codebuild/output/src3059167450/src/Vepo.Infrastructure/Search/Search.cs:line 42
Jul 31 01:22:14 ip-172-31-1-234 web: at Vepo.Web.Startup.b__8_7(IServiceProvider serviceProvider) in /codebuild/output/src3059167450/src/Vepo.Web/Startup.cs:line 211
...(后续栈信息省略)
相关代码(Startup.cs)
services.AddScoped<ISearchService, SearchService>(serviceProvider => { return new SearchService( Configuration["openSearchEndpoint"], Configuration["openSearchUsername"], Configuration["openSearchPassword"], Configuration["openSearchIndexName"]); }); services.AddScoped<IGroceryItmsSearchIndexService, GroceryItmsSearchIndexService>();
核心原因是配置文件未被正确包含到发布包中,导致Configuration["openSearchXXX"]读取值为null,创建SearchService时触发ArgumentNullException,进而导致依赖注入容器无法完成IGroceryItmsSearchIndexService的解析(因为它依赖的ISearchService初始化失败)。
手动部署正常是因为手动发布的build文件夹中包含了appsettings.json,但CodePipeline的CodeBuild环节存在以下可能问题:
- artifacts配置错误,未正确包含发布目录下的配置文件
- 项目中
appsettings.json的复制属性未设置,dotnet publish未将其复制到发布目录 - EBS环境中未配置对应的环境变量,导致配置读取失败
1. 确保配置文件的复制属性正确
在项目的.csproj文件中添加配置,确保appsettings.json及环境对应配置文件被复制到发布目录:
<ItemGroup> <Content Update="appsettings.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> <Content Update="appsettings.Production.json"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Content> </ItemGroup>
2. 修正buildspec.yml的artifacts配置
当前artifacts会打包整个项目目录,改为只包含发布后的./app目录内容,避免冗余文件:
artifacts: files: - "./app/**/*" base-directory: "."
3. 同步EBS环境变量
如果手动部署时通过EBS控制台设置了openSearchEndpoint等变量,需在CodePipeline对应的EBS环境中同步:
- 进入Elastic Beanstalk控制台,找到目标环境
- 点击配置 > 软件,在环境属性中添加
openSearchEndpoint、openSearchUsername等变量
4. 优化buildspec.yml构建步骤
简化restore和build流程,dotnet restore可自动恢复所有项目依赖,dotnet publish会自动执行build,无需单独构建:
pre_build: commands: - dotnet restore # 移除build阶段 post_build: commands: - dotnet publish -r linux-x64 --self-contained true -c Release -o ./app/ Vepo.Web/Vepo.Web.csproj
内容的提问来源于stack exchange,提问作者BeniaminoBaggins

