在 Docker Compose 堆栈中通过 Npgsql 从 ASP.NET Core 6 连接到 PostgreSql

Naf*_*tis 4 postgresql docker asp.net-core-webapi .net-6.0

我正在尝试创建一个 docker-compose 脚本来启动具有 PostgreSql 数据库和 ASP.NET Core 6 Web API 的堆栈。为了测试该场景,我使用默认模板创建了一个新的 ASP.NET Core 6 Web API。然后我添加了 NuGet 包Npgsql(6.0.3)和一个仅查询数据库引擎版本的示例控制器,例如:

[ApiController]
[Produces("application/json")]
public class TestController : Controller
{
    private readonly IConfiguration _config;

    public TestController(IConfiguration config)
    {
        _config = config;
    }

    [HttpGet("api/dbversion")]
    public IActionResult GetVersion()
    {
        using NpgsqlConnection conn = new(_config.GetConnectionString("Default"));

        conn.Open();

        var cmd = conn.CreateCommand();
        cmd.CommandText = "SELECT version();";

        return Ok($"Version: {cmd.ExecuteScalar() as string}");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我为此 API 创建了 Docker 映像,并编写了一个 docker-compose 脚本,如下所示:

version: '3.7'

services:
  test-db:
    image: postgres
    # explicit container name
    # another approach using hostname: https://stackoverflow.com/questions/68701716/docker-compose-postgres-connection-refused
    container_name: test-db
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=postgres
    ports:
      - 5433:5432
    networks:
      - test-network

  test-api:
    image: MYREPONAME/test-api:0.0.1
    ports:
      - 5154:80
    depends_on:
      - test-db
    environment:
      - CONNECTIONSTRINGS__DEFAULT=User ID=postgres;Password=postgres;Host=test-db;Port=5433;Database=postgres
    networks:
      - test-network

networks:
  test-network:
    driver: bridge
Run Code Online (Sandbox Code Playgroud)

在这里,我使用官方postgres映像,设置默认凭据,将服务重定向到组合堆栈中的端口 5433,并从同一网络内的 API 使用它。我正在覆盖脚本中的连接字符串,使用容器名称 ( test-db) 作为主机名;localhost在 Docker 网络中不会是一个选项(例如参见此处此处)。

当我从 Ubuntu 主机触发此脚本时,我可以访问端口 5433 处的数据库服务和 localhost:5154/swagger/index.html 处的 Web API。然而,当我运行应该连接到数据库的操作时,即使我可以清楚地看到数据库服务 IP 和端口,我也会收到连接拒绝错误:

"Exception":"Npgsql.NpgsqlException (0x80004005): Failed to connect to 172.27.0.2:5433  
---\u003E System.Net.Sockets.SocketException (111): Connection refused    
at Npgsql.Internal.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
at Npgsql.Internal.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
at Npgsql.Internal.NpgsqlConnector.RawOpen(SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.Internal.NpgsqlConnector.\u003COpen\u003Eg__OpenCore|191_1(NpgsqlConnector conn, SslMode sslMode, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.Internal.NpgsqlConnector.Open(NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.ConnectorPool.OpenNewConnector(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.ConnectorPool.\u003CGet\u003Eg__RentAsync|28_0(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.\u003COpen\u003Eg__OpenAsync|45_0(Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.Open()  
...
Run Code Online (Sandbox Code Playgroud)

Han*_*ian 7

当一个容器连接到桥接网络上的另一个容器时,您可以使用容器端口。不是主机上的映射端口。所以你的连接字符串应该是

CONNECTIONSTRINGS__DEFAULT=User ID=postgres;Password=postgres;Host=test-db;Port=5432;Database=postgres
Run Code Online (Sandbox Code Playgroud)