0

I have a .NET Core application running in docker that connect to MySQL database on docker,

when MySQL docker container run with docker run command :

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

I don't get the error, but when I try using docker-compose I got this error :

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)

After hours of trying different things I find googling, still can't connect to MySQL.

here is my 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

and this my 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

and my DataAccess class

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];
        }
    }
}

Update

I'm have try to change the Port = 3360 in environment

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 and got this exception:

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)

Here is my 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"]

and here my .csproj file

<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>

I just follow this article

6
  • database0 and database1 containers run on 3306 ports, the webservice container should try to connect to them on 3306 ports only.... Commented Jul 8, 2021 at 8:31
  • already change this port 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 to 3306, but still got the same errors Commented Jul 8, 2021 at 8:36
  • Please try using port=3306 Commented Jul 8, 2021 at 8:50
  • yes, got this error : ConnectionString: server=database0; port=3306; database=post; user=root; password=pw; Persist Security Info=False; Connect Timeout=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 "0HMA1TRRU6KQC", Request id "0HMA1TRRU6KQC:00000002": An unhandled exception was thrown by the application. System.TypeInitializationException: The type initializer for 'MySql.Data.MySqlClient.Replication. Commented Jul 8, 2021 at 9:04
  • You are setting PostDbConnectionStrings__Shard0 and PostDbConnectionStrings__Shard1 environment variables in Docker-compose. In code you are trying to read the configuration from the configuration section, which I believe comes from appSettings.json file. How are you pushing environment variable values to the appSettings.json file? Commented Jul 8, 2021 at 9:23

1 Answer 1

5

You haven't shown the Dockerfile for your application, but I'm guessing you're using dotnet publish to create a single-file application.

As the exception message says:

System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize

System.NotSupportedException: CodeBase is not supported on assemblies loaded from a single-file bundle.

The .NET MySQL library you are using (MySql.Data) is dependent on ConfigurationManager, which is causing this exception. You have two options:

  1. Stop publishing your application as a single file.
  2. Switch to MySqlConnector, which is a more modern MySQL .NET library that fully supports .NET Core.

To stop publishing as a single file, change the RUN dotnet publish block in your Dockerfile to:

RUN dotnet publish "PostService.csproj" -c Release -o /app/publish \
    --no-restore \
    --runtime alpine-x64 \
    --self-contained true
Sign up to request clarification or add additional context in comments.

1 Comment

I just update my question with adding the dockerfile and .csproj, and just try the options 2 but seems like I have to change my code, too much effort, how about the option 1, what line I have to change in my docker file..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.