如何解决 docker-compose 环境变量不起作用 ASP.Net Core MVC
Posted
技术标签:
【中文标题】如何解决 docker-compose 环境变量不起作用 ASP.Net Core MVC【英文标题】:How to solve docker-compose environment variables not working ASP.Net Core MVC 【发布时间】:2021-06-12 01:25:24 【问题描述】:我在 docker-compose 文件中的配置变量无法在 Startup.cs 中读取。我正在使用 Asp.net Core 3.1 和 SQL Server。
这是我的错误信息
blog-app_1 | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository[60]
blog-app_1 | 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.
blog-app_1 | warn: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[35]
blog-app_1 | No XML encryptor configured. Key 58394e97-3215-43de-abbc-ae7ab801d661 may be persisted to storage in unencrypted form.
blog-app_1 | crit: Microsoft.AspNetCore.Hosting.Diagnostics[6]
blog-app_1 | Application startup exception
blog-app_1 | System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
blog-app_1 | at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
blog-app_1 | at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction)
blog-app_1 | at BlogApplication.Startup.<>c__DisplayClass4_0.<ConfigureServices>b__1(DbContextOptionsBuilder options) in /src/BlogApplication/Startup.cs:line 56
blog-app_1 | at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_0`2.<AddDbContext>b__0(IServiceProvider p, DbContextOptionsBuilder b)
blog-app_1 | at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action`2 optionsAction)
这是我的 Startup.cs
我使用Configuration["..."]
来初始化环境变量。
您可以在 public void ConfigureServices(IServiceCollection services) 中看到它。
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
services.AddControllersWithViews().AddJsonOptions(option =>
option.JsonSerializerOptions.PropertyNamingPolicy = null;
option.JsonSerializerOptions.DictionaryKeyPolicy = null;
);
//Config Database Identity
var server_identity = Configuration["DBServer"] ?? "mssql-server";
var port_identity = Configuration["DBPort"] ?? "1433";
var user_identity = Configuration["DBUsername"] ?? "sa";
var password_identity = Configuration["DBPass"] ?? "Loc@04071999";
var dbName_identity = Configuration["DBNameIdentity"] ?? "Identity_BlogApplication";
//Config Database Blog
var dbName_blog = Configuration["DBNameBlog"] ?? "Data_BlogApplication";
string DefaultConnection = $"Server=server_identity, port_identity; Database=dbName_identity; User ID=user_identity; Password=password_identity";
string DataConnection = $"Server=server_identity, port_identity; Database=dbName_blog; User ID=user_identity; Password=password_identity";
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString(DefaultConnection)));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString(DataConnection)));
services.AddTransient<ICommentService, CommentService>();
services.AddTransient<IBlogService, BlogService>();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddRazorPages();
//services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
else
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
endpoints.MapControllerRoute(
name: "default",
pattern: "controller=Blog/action=Index/id?");
endpoints.MapRazorPages();
);
app.ApplicationServices.CreateScope().ServiceProvider.GetService<ApplicationDbContext>().Database.Migrate();
app.ApplicationServices.CreateScope().ServiceProvider.GetService<BlogApplicationDbContext>().Database.Migrate();
c
这是我的 docker-compose.xml
在 docker-compose 中,我为 blog-app 设置了“环境:”
version: '3'
services:
mssql-server:
image: "microsoft/mssql-server-linux"
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "Loc@04071999"
MSSQL_PID: Express
ports:
- "1433:1433"
blog-app:
build: .
environment:
DBServer: "mssql-server"
DBPort: "1433"
DBUsername: "sa"
DBPass: "Loc@04071999"
DBNameIdentity: "Identity_BlogApplication"
DBNameBlog: "Data_BlogApplication"
ports:
- "3000:80"
感谢您看到我的问题
【问题讨论】:
【参考方案1】:您使用的方法Configuration.GetConnectionString() 从配置中获取具有提供名称的连接字符串。在您的情况下,名称是变量DefaultConnection
的值。变量应该有值
$"Server=mssql-server, 1433; Database=Identity_BlogApplication; User ID=sa; Password=Loc@04071999";
但不存在具有此名称的连接字符串,因此返回null
,您将获得ArgumentNullException
。
您可以通过不调用Configuration.GetConnectionString()
而是将连接字符串直接传递给方法UseSqlServer
来修复它,因为您自己使用环境变量的值构建连接字符串。
所以以下应该可以解决您的问题。
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(DefaultConnection));
...
services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(DataConnection));
但是恕我直言,您不应该自己构建连接字符串,而是使用单个环境变量向您的数据库提供完整的连接字符串。这是使用连接字符串环境变量 (CONNECTIONSTRINGS
)
version: '3'
services:
mssql-server:
image: "microsoft/mssql-server-linux"
environment:
ACCEPT_EULA: "Y"
SA_PASSWORD: "Loc@04071999"
MSSQL_PID: Express
ports:
- "1433:1433"
blog-app:
build: .
environment:
CONNECTIONSTRINGS__IDENTITY: "Server=mssql-server, 1433; Database=Identity_BlogApplication; User ID=sa; Password=Loc@04071999"
CONNECTIONSTRINGS__BLOG: "Server=mssql-server, 1433; Database=Data_BlogApplication; User ID=sa; Password=Loc@04071999"
ports:
- "3000:80"
使用这种方法,您可以在代码中调用Configuration.GetConnectionString()
,例如
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("IDENTITY")));
...
services.AddDbContext<BlogApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("BLOG")));
【讨论】:
感谢您的帮助。我按照你的修复,但我有一个新问题 这是我的新问题:blog-app_1 |暴击:Microsoft.AspNetCore.Hosting.Diagnostics[6] blog-app_1 |应用程序启动异常 blog-app_1 | Microsoft.Data.SqlClient.SqlException (0x80131904):建立与 SQL Server 的连接时发生与网络相关或特定于实例的错误。服务器未找到或无法访问。验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。 (提供者:TCP 提供者,错误:40 - 无法打开与 SQL Server 的连接) 我已经解决了我的问题。在 docker-compose 文件中更改这一行: image: "microsoft/mssql-server-linux --change-> image: "mcr.microsoft.com/mssql/server:2019-latest" 非常感谢。关闭我的话题!以上是关于如何解决 docker-compose 环境变量不起作用 ASP.Net Core MVC的主要内容,如果未能解决你的问题,请参考以下文章
如何使用来自其他目录的 docker-compose 环境变量
docker-compose环境会覆盖jar中的变量,docker环境变量和jar中的变量是如何映射的?
如何将环境变量从 docker-compose 传递给项目?
如何从.env文件获取环境变量到docker-compose.yml?