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



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

[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}");
}
}

然后,我为这个API创建了Docker镜像,并编写了一个Docker-composite脚本,如下所示:

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

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

当我从Ubuntu主机启动这个脚本时,我可以访问5433端口的DB服务,以及localhost:5154/swagger/index.html的web API。然而,当我运行应该连接到数据库的操作时,我得到了一个连接拒绝错误,尽管我可以清楚地看到DB服务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.u003COpenu003Eg__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.u003CGetu003Eg__RentAsync|28_0(NpgsqlConnection conn, NpgsqlTimeout timeout, Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.u003COpenu003Eg__OpenAsync|45_0(Boolean async, CancellationToken cancellationToken)
at Npgsql.NpgsqlConnection.Open()  
...

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

CONNECTIONSTRINGS__DEFAULT=User ID=postgres;Password=postgres;Host=test-db;Port=5432;Database=postgres

最新更新