ASP Dotnet Core MVC 与 Docker 连接到 Postgresql

3

我一直在为将ASP Dotnet应用程序做成Docker容器的问题而苦恼。我已经在StackOverflow上寻找了很长时间,但没有成功。

基本上,我要实现的目标是在Docker容器中运行我的ASP Dotnet应用程序(MVC API),并且我也希望我的Postgresql实例在同一个网络中运行。

我创建了一个像这样的docker-compose文件:

version: '3'
networks:
  asp-dotnet-network:
    driver: bridge

services:
  postgres:
    image: postgres:9.6.21-alpine
    container_name: postgres
    ports:
      - "5433:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
    networks:
      - asp-dotnet-network
      
  app:
    build: ../.
    container_name: app
    ports:
      - "5000:5000"
      - "5001:5001"
    environment:
      - ConnectionStrings__Default=Host=postgres;Username=postgres;Port=5432;Password=postgres;Database=postgres;Pooling=true;
    depends_on:
      - postgres
    networks:
      - asp-dotnet-network

我的 Dockerfile 如下所示

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /app

COPY *.sln .

COPY Data/Data.csproj ./Data/
COPY Application/Application.csproj ./Application/
COPY WebApi/WebApi.csproj ./WebApi/

RUN dotnet restore

COPY Data/. ./Data/
COPY Application/. ./Application/
COPY WebApi/. ./WebApi/

WORKDIR /app/WebApi
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS runtime
WORKDIR /app

COPY --from=build /app/WebApi/out ./
ENTRYPOINT ["dotnet", "WebApi.dll"]

最后,我已经配置了我的主要应用程序以接受环境变量,这样我就可以覆盖appsettings:
        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); })
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddJsonFile("appsettings.json").
                        AddJsonFile($"appsettings.docker.json", true).AddEnvironmentVariables();
                });

当我在包含docker-compose.yml文件的目录中运行docker-compose up --build && docker-compose logs -f命令时,应用程序容器会发生以下错误:
app         | fail: Microsoft.EntityFrameworkCore.Database.Connection[20004]
app         |       An error occurred using the connection to database 'postgres' on server 'tcp://postgres:5432'.
app         | fail: Microsoft.EntityFrameworkCore.Query[10100]
app         |       An exception occurred while iterating over the results of a query for context type 'DatabaseContext'.
app         |       System.InvalidOperationException: An exception has been raised that is likely due to a transient failure.
app         |        ---> Npgsql.NpgsqlException (0x80004005): Exception while connecting
app         |        ---> System.Net.Sockets.SocketException (111): Connection refused

一开始我以为这是网络问题,但是当我在我的应用容器中执行ping命令时,我可以找到postgres容器。我还尝试在应用容器中安装psql,即使这样我也可以访问我的postgres数据库。

我很茫然,有人知道问题出在哪里吗?


你暴露了5433端口,但是定义的是5432端口。请尝试更改一下。- "5433:5432" - Mustafa Güler
@MustafaGüler 感谢您的回复。我的理解是,通过添加“5433:5432”,我只绑定了5433作为外部可访问端口。正如我在帖子中所述,我可以通过ping(和psql连接)到5432端口来连接postgres容器。我已更改连接字符串中的端口,但遗憾的是它并没有解决问题。 - danielr
你能分享一下 ConnectionStrings / DbContext 吗? - Mustafa Güler
两个问题:1. 您使用的是 default 的Postgres镜像,我认为您没有Postgres数据库。2. 如果您使用带有Postgres数据库的 custom 镜像,请在2分钟后重新加载应用程序,我猜测当您尝试从Web应用程序连接时,数据库可能还没有完全启动。 - Max
@Max,我不确定我理解你的第一个问题。我正在使用postgres:9.6.21(在我的示例中,我使用了postgres:9.6.21-alpine,后来我得出结论我实际上并不需要它)。这是包含数据库的postgres基础镜像,对吗?我通过从本地机器连接到它来验证数据库是否已启动,似乎可以工作。至于你的第二个问题,那很可能是原因。我看到我的应用程序在Docker-compose日志中崩溃,然后docker-compose日志显示数据库已经完成启动。你有什么建议,我如何让应用程序重新加载? - danielr
2个回答

1

0

这对我很有帮助

如果有人要求更多关于如何在net minimal API中实现它的细节

使用上面配置的相同的docker文件和解决方案链接(使用service_healthy检查) 然后我在Program.cs上进行了以下修改

    builder.Host.ConfigureAppConfiguration((hostingContext, config) =>
    {
        config.AddJsonFile("appsettings.json").
        AddJsonFile($"appsettings.docker.json", 
    true).AddEnvironmentVariables();
    });

    var connectionString = builder.Configuration.GetConnectionString("Default")
        ?? "Host = localhost; Database = xxxxx; Username = xxxxx; Password = 
        xxxx; Pooling = true; ";

    builder.Services.AddDbContext<DbContext>(opt =>
            opt.UseNpgsql(connectionString));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接