.NET 6 Blazor容器编译时ServiceProvider.GetRequiredService抛出异常
问题:Blazor .NET 6容器化后无法连接MySQL主机
基于.NET 6的Blazor应用本地调试正常,但容器化编译运行时,在Program.cs启动阶段初始化数据库的代码中(第115行获取ApplicationDbContext时)抛出MySQL连接异常,错误提示Unable to connect to any of the specified MySQL hosts。本地构建镜像命令为docker build --file dockerfile --tag test/hermes:latest .。
初始化代码片段:
using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); // 如果数据库已创建则返回True,若已存在则返回False。 if (db.Database.EnsureCreated()) { var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>(); var userManager = scope.ServiceProvider.GetRequiredService<UserManager<IdentityUser>>(); DataInitializer.InitData(roleManager, userManager).Wait(); // 用于创建数据库架构 var hermesCtx = scope.ServiceProvider.GetService<IHermesContext>(); string pathSql = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Scripts", "ConsultantsDb.sql"); await hermesCtx.CreateTablesAsync(pathSql); } }
错误堆栈关键信息:
warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60] Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. Unhandled exception. MySqlConnector.MySqlException (0x80004005): Unable to connect to any of the specified MySQL hosts. ... at Program.<Main>$(String[] args) in /src/Hermes/Program.cs:line 115
解决方案
修正连接字符串的主机配置
本地调试用localhost或127.0.0.1可访问宿主机MySQL,但容器内无法直接识别该地址:- 若MySQL运行在宿主机:容器内改用宿主机的局域网IP(如
192.168.x.x),或启动容器时加--network host参数共享宿主机网络; - 若MySQL也是容器化部署:确保两者在同一个Docker网络,连接字符串主机名用MySQL容器的名称(如
mysql-container)。
- 若MySQL运行在宿主机:容器内改用宿主机的局域网IP(如
验证容器网络连通性
启动容器进入交互式模式测试MySQL连接:docker run -it --rm test/hermes:latest bash # 若容器基于Alpine,先安装MySQL客户端 apk add mysql-client # 测试连接 mysql -h <mysql-host> -u <username> -p连接失败则排查Docker网络配置、MySQL防火墙/安全组规则(是否允许容器IP访问3306端口)。
调整MySQL绑定地址与服务状态
检查MySQL配置文件(my.cnf/my.ini)的bind-address参数,改为0.0.0.0允许所有IP访问;同时确认MySQL服务正常运行,且容器所在网络能通MySQL的3306端口。确认容器环境变量配置
确保容器启动时正确传递数据库连接字符串的环境变量,避免硬编码:docker run -e "ConnectionStrings__DefaultConnection=server=<mysql-host>;user=<user>;password=<pass>;database=<db>" test/hermes:latest可在容器内打印环境变量,验证读取的配置值是否正确。
添加数据库连接重试逻辑
若MySQL与应用容器同时启动,可能出现应用先启动而MySQL未就绪的情况,可在初始化代码中添加重试:using (var scope = app.Services.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>(); int retryCount = 5; bool connected = false; while (retryCount > 0 && !connected) { try { await db.Database.OpenConnectionAsync(); connected = true; } catch (MySqlException) { retryCount--; await Task.Delay(2000); } } if (!connected) throw new InvalidOperationException("无法连接到MySQL数据库"); // 后续初始化逻辑... }
内容的提问来源于stack exchange,提问作者Ryck
相关产品推荐
相关产品推荐

