在 Docker 容器中运行 .Net 5 API 时无法连接到 Postgres

Posted

技术标签:

【中文标题】在 Docker 容器中运行 .Net 5 API 时无法连接到 Postgres【英文标题】:Can't connect to Postgres when running .Net 5 API in Docker container 【发布时间】:2021-10-01 01:21:41 【问题描述】:

我正在尝试将在 Docker 容器中运行的 .Net 5 API 与在单独容器中运行的 Postgres db 连接起来。在没有容器的情况下在本地运行 API 时连接有效,但是当我在容器中运行 API 时出现错误

使用连接到服务器“tcp://localhost:5432”上的数据库“databasename”时出错。

我认为这是因为 docker 容器没有在 localhost 上运行。 我试图更改 docker-compose 文件中的主机,并尝试手动更改 startup.cs 中的连接字符串。这会更改 API 在本地运行时使用的连接,但不会更改容器内的连接或我收到的错误。任何帮助将不胜感激。

Startup.cs

//var connectionString = Configuration.GetSection(nameof(PostgresSettings)).Get<PostgresSettings>().ConnectionString;
var connectionString = $"Host=tryingtochangehost;Port=5432;Database=databasename;Username=username;Password=password";
services.AddDbContext<DataContext>(options => options.UseNpgsql(connectionString));
services.AddScoped<IDataContext>(provider => provider.GetService<DataContext>());

docker-compose.yml

version: "3.4"

services:
  web:
    build: .
    ports:
      - "8080:80"
    environment:
      - JWTCONFIG:SECRET=secret
      - POSTGRESSETTINGS:PASSWORD=password
      - POSTGRESSETTINGS:HOST=postgresql_database
    depends_on:
      - "postgresql_database"
    networks:
      - mynetwork

  postgresql_database:
    image: postgres:latest
    environment:
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=databasename
    ports:
      - "5432:5432"
    restart: always
    volumes:
      - database-data:/var/lib/postgresql/data/
    networks:
      - mynetwork

  pgadmin:
    image: dpage/pgadmin4
    environment:
      - PGADMIN_DEFAULT_EMAIL=pgadmin@admin.org
      - PGADMIN_DEFAULT_PASSWORD=password
    ports:
      - "5050:80"
    restart: always
    volumes:
      - pgadmin:/root/.pgadmin
    networks:
      - mynetwork

volumes:
  database-data:
  pgadmin:

networks:
  mynetwork:
    driver: bridge

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:5.0-focal AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0-focal AS build
WORKDIR /src
COPY ["Server.csproj", "./"]
RUN dotnet restore "Server.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "Server.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "Server.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "Server.dll"]

appsettings.json


  "PostgresSettings": 
    "Host": "localhost",
    "Port": "5432",
    "Database": "databasename",
    "Username": "admin"
  ,
  "Logging": 
    "LogLevel": 
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    
  ,
  "JwtConfig": ,
  "AllowedHosts": "*"

【问题讨论】:

【参考方案1】:

当您尝试连接到 localhost:5432 时,您正在尝试连接到与您的 Web 容器相同的容器。

Docker compose 创建了一个虚拟网络,每个容器都可以通过它的服务名称访问。因此,您需要在 appsettings 中将数据库服务器名称从 localhost 更改为 postgresql_database


  "PostgresSettings": 
    "Host": "postgresql_database",
    "Port": "5432",
    "Database": "databasename",
    "Username": "admin"
  ,
  "Logging": 
    "LogLevel": 
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    
  ,
  "JwtConfig": ,
  "AllowedHosts": "*"

你的连接字符串代码应该是

var connectionString = $"Host=postgresql_database;Port=5432;Database=databasename;Username=username;Password=password";

【讨论】:

您好,感谢您的帮助。更改连接字符串或 appsettings 只会在 api 不在容器中运行时影响它。甚至手动更改连接字符串,例如 services.AddDbContext(options => options.UseNpgsql("notarealconnectionstring"));只有在没有容器的情况下运行 API 时才会产生影响。似乎无论字符串实际上是什么,容器都会尝试在 tcp://localhost:5432 连接到数据库,【参考方案2】:

事实证明我的配置很好,但是我需要在 docker-compose up 之前运行 docker-compose build,这样更改才会真正生效。

【讨论】:

以上是关于在 Docker 容器中运行 .Net 5 API 时无法连接到 Postgres的主要内容,如果未能解决你的问题,请参考以下文章

在 overlay 中运行容器 - 每天5分钟玩转 Docker 容器技术(51)

CentOS7的docker中运行.Net 5 API项目

将已发布的 .Net Core Web API 文件和公共 selenium/standalone-chrome 容器合并到一个 Docker 容器中

ASP.NET Core 5 + SQL Server Docker 容器:无效的撰写项目

需要帮助对 linux Docker 中的 .NET Core 2.1 API 进行故障排除

Calico 的网络结构是什么?- 每天5分钟玩转 Docker 容器技术(68)