![](/img/trans.png)
[英]How to connect application with MySQL by Docker-compose use custom server name in ConnectionStrings?
[英]Why does my .NET web API application not connect to MySQL on docker when using docker-compose?
我有一個在 docker 中運行的 .NET Core 應用程序,它連接到 docker 上的 MySQL 數據庫,
當 MySQL docker 容器使用 docker run 命令運行時:
C:\dev>docker run -p 3310:3306 --name=mysql1 -e MYSQL_ROOT_PASSWORD=pw -d mysql:5.6
C:\dev>docker run -p 3311:3306 --name=mysql2 -e MYSQL_ROOT_PASSWORD=pw -d mysql:5.6
我沒有收到錯誤消息,但是當我嘗試使用 docker-compose 時出現此錯誤:
ConnectionString: server=database0; port=3312; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
ConnectionString: server=database1; port=3313; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMA1R75ALK39", Request id "0HMA1R75ALK39:00000002": An unhandled exception was thrown by the application.
System.TypeInitializationException: The type initializer for 'MySql.Data.MySqlClient.Replication.ReplicationManager' threw an exception.
---> System.TypeInitializationException: The type initializer for 'MySql.Data.MySqlClient.MySqlConfiguration' threw an exception.
---> System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.NotSupportedException: CodeBase is not supported on assemblies loaded from a single-file bundle.
at System.Reflection.RuntimeAssembly.get_CodeBase()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at MySql.Data.MySqlClient.MySqlConfiguration..cctor()
--- End of inner exception stack trace ---
at MySql.Data.MySqlClient.MySqlConfiguration.get_Settings()
at MySql.Data.MySqlClient.Replication.ReplicationManager..cctor()
--- End of inner exception stack trace ---
at MySql.Data.MySqlClient.Replication.ReplicationManager.IsReplicationGroup(String groupName)
at MySql.Data.MySqlClient.MySqlConnection.Open()
at System.Data.Common.DbConnection.OpenAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location ---
at MySql.EntityFrameworkCore.MySQLDatabaseCreator.<>c__DisplayClass20_0.<<ExistsAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at MySql.EntityFrameworkCore.Storage.Internal.MySQLExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureDeletedAsync(CancellationToken cancellationToken)
at PostService.Data.DataAccess.InitDatabase(Int32 countUsers, Int32 countCategories)
at PostService.Controllers.PostsController.InitDatabase(Int32 countUsers, Int32 countCategories)
at lambda_method4(Closure , Object )
at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
經過幾個小時的嘗試,我發現在谷歌上搜索了不同的東西,但仍然無法連接到 MySQL。
這是我的 docker-compose.yaml
version: '3.8'
services:
webservice:
image: 'ariefs/postservice:v1.0.0'
cpus: 0.5
scale: 4
environment:
- PostDbConnectionStrings__Shard0=server=database0; port=3312; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
- PostDbConnectionStrings__Shard1=server=database1; port=3313; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
# - PostDbConnectionStrings__Shard2=server=database2; port=3306; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
loadbalancer:
image: dockercloud/haproxy
links:
- webservice
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 5001:80
database0:
image: 'mysql:5.6'
cpus: 0.5
ports:
- 3312:3306
environment:
- MYSQL_ROOT_PASSWORD=pw
database1:
image: 'mysql:5.6'
cpus: 0.5
ports:
- 3313:3306
environment:
- MYSQL_ROOT_PASSWORD=pw
database2:
image: 'mysql:5.6'
cpus: 0.5
ports:
- 3314:3306
environment:
- MYSQL_ROOT_PASSWORD=pw
這是我的 docker ps :
❯ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES
668b32b68d0f dockercloud/haproxy "/sbin/tini -- docke…" 3 minutes ago Up 3 minutes 443/tcp, 1936/tcp, 0.0.0.0:5001->80/tcp, :::5001->80/tcp postservice_loadbalancer_1
a2f3be18868c ariefs/postservice:v1.0.0 "./PostService --url…" 3 minutes ago Up 3 minutes 80/tcp
postservice_webservice_3
ac8c9d791cc5 ariefs/postservice:v1.0.0 "./PostService --url…" 3 minutes ago Up 3 minutes 80/tcp
postservice_webservice_2
7fe86c655063 ariefs/postservice:v1.0.0 "./PostService --url…" 3 minutes ago Up 3 minutes 80/tcp
postservice_webservice_4
5105d0472f78 ariefs/postservice:v1.0.0 "./PostService --url…" 3 minutes ago Up 3 minutes 80/tcp
postservice_webservice_1
f8f8e5a1ed86 mysql:5.6 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 0.0.0.0:3313->3306/tcp, :::3313->3306/tcp postservice_database1_1
c4aafd2b2182 mysql:5.6 "docker-entrypoint.s…" 3 minutes ago Up 3 minutes 0.0.0.0:3312->3306/tcp, :::3312->3306/tcp postservice_database0_1
和我的 DataAccess 類
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using PostService.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace PostService.Data
{
public class DataAccess
{
private readonly List<string> _connectionStrings = new List<string>();
public DataAccess(IConfiguration configuration)
{
var connectionStrings = configuration.GetSection("PostDbConnectionStrings");
foreach (var connectionString in connectionStrings.GetChildren())
{
Console.WriteLine("ConnectionString: " + connectionString.Value);
_connectionStrings.Add(connectionString.Value);
}
}
public async Task<ActionResult<IEnumerable<Post>>> ReadLatestPosts(string category, int count)
{
using var dbContext = new PostServiceContext(GetConnectionString(category));
return await dbContext.Post.OrderByDescending(p => p.PostId)
.Take(count)
.Include(x => x.User)
.Where(p => p.CategoryId == category)
.ToListAsync();
}
public async Task<int> CreatePost(Post post)
{
using var dbContext = new PostServiceContext(GetConnectionString(post.CategoryId));
dbContext.Post.Add(post);
return await dbContext.SaveChangesAsync();
}
public async Task InitDatabase(int countUsers, int countCategories)
{
foreach (var connectionString in _connectionStrings)
{
using var dbContext = new PostServiceContext(connectionString);
await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.EnsureDeletedAsync();
for (int i = 1; i <= countUsers; i++)
{
await dbContext.User.AddAsync(new User { Name = "User" + i, Version = 1 });
await dbContext.SaveChangesAsync();
}
for (int i = 1; i <= countCategories; i++)
{
await dbContext.Category.AddAsync(new Category { CategoryId = "Category" + i });
await dbContext.SaveChangesAsync();
}
}
}
private string GetConnectionString(string category)
{
using var md5 = MD5.Create();
var hash = md5.ComputeHash(Encoding.ASCII.GetBytes(category));
var x = BitConverter.ToUInt16(hash, 0) % _connectionStrings.Count;
return _connectionStrings[x];
}
}
}
更新
我嘗試更改環境中的端口 = 3360
環境: - PostDbConnectionStrings__Shard0=server=database0; 端口=3312; 數據庫=帖子; 用戶=root; 密碼=密碼; 持久安全信息=假; 連接超時=300
- PostDbConnectionStrings__Shard1=server=database1; 端口=3313; 數據庫=帖子; 用戶=root; 密碼=密碼; 持久安全信息=假; 連接超時=300
# - PostDbConnectionStrings__Shard2=server=database2; 端口=3306; 數據庫=帖子; 用戶=root; 密碼=密碼; 持久安全信息=假; 連接超時=300 並收到此異常:
ConnectionString: server=database1; port=3306; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=300
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMA1U8GBSBGK", Request id "0HMA1U8GBSBGK:00000002": An unhandled exception was thrown by the application.
System.TypeInitializationException: The type initializer for 'MySql.Data.MySqlClient.Replication.ReplicationManager' threw an exception.
---> System.TypeInitializationException: The type initializer for 'MySql.Data.MySqlClient.MySqlConfiguration' threw an exception.
---> System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.NotSupportedException: CodeBase is not supported on assemblies loaded from a single-file bundle.
at System.Reflection.RuntimeAssembly.get_CodeBase()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at MySql.Data.MySqlClient.MySqlConfiguration..cctor()
--- End of inner exception stack trace ---
at MySql.Data.MySqlClient.MySqlConfiguration.get_Settings()
at MySql.Data.MySqlClient.Replication.ReplicationManager..cctor()
--- End of inner exception stack trace ---
at MySql.Data.MySqlClient.Replication.ReplicationManager.IsReplicationGroup(String groupName)
at MySql.Data.MySqlClient.MySqlConnection.Open()
at System.Data.Common.DbConnection.OpenAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location ---
at MySql.EntityFrameworkCore.MySQLDatabaseCreator.<>c__DisplayClass20_0.<<ExistsAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at MySql.EntityFrameworkCore.Storage.Internal.MySQLExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalDatabaseCreator.EnsureDeletedAsync(CancellationToken cancellationToken)
at PostService.Data.DataAccess.InitDatabase(Int32 countUsers, Int32 countCategories)
at PostService.Controllers.PostsController.InitDatabase(Int32 countUsers, Int32 countCategories)
at lambda_method4(Closure , Object )
at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.AwaitableResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
這是我的 dockerfile
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine AS publish
WORKDIR /src
COPY ["PostService.csproj", "./"]
RUN dotnet restore "PostService.csproj" --runtime alpine-x64
COPY . .
RUN dotnet publish "PostService.csproj" -c Release -o /app/publish \
--no-restore \
--runtime alpine-x64 \
--self-contained true \
/p:PublishTrimmed=true \
/p:PublishSingleFile=true
FROM mcr.microsoft.com/dotnet/runtime-deps:5.0-alpine AS final
RUN adduser --disabled-password \
--home /app \
--gecos '' dotnetuser && chown -R dotnetuser /app
RUN apk upgrade musl
USER dotnetuser
WORKDIR /app
EXPOSE 80
COPY --from=publish /app/publish .
ENTRYPOINT ["./PostService", "--urls", "http://0.0.0.0:80"]
這里是我的 .csproj 文件
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="MySql.EntityFrameworkCore" Version="5.0.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.4" />
</ItemGroup>
</Project>
我只關注這篇文章
您尚未顯示應用程序的 Dockerfile,但我猜您正在使用dotnet publish
創建單文件應用程序。
正如異常消息所說:
System.Configuration.ConfigurationErrorsException:配置系統初始化失敗
System.NotSupportedException:從單文件包加載的程序集不支持 CodeBase。
您使用的 .NET MySQL 庫 (MySql.Data) 依賴於ConfigurationManager
,這會導致此異常。 您有兩個選擇:
要停止作為單個文件RUN dotnet publish
,請將Dockerfile
的RUN dotnet publish
塊Dockerfile
為:
RUN dotnet publish "PostService.csproj" -c Release -o /app/publish \
--no-restore \
--runtime alpine-x64 \
--self-contained true
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.