无法将Npgsql连接到在Docker上运行的Postgres DB

时间:2017-01-03 15:22:51

标签: .net postgresql docker npgsql

我有一个带有.NET应用程序的docker容器,代码如下:

var pgsql = OpenDbConnection("Server=localhost;Database=postgres;Username=postgres;Password=MyPass;Port=5432");

private static NpgsqlConnection OpenDbConnection(string connectionString)
        {
            NpgsqlConnection connection;
            Console.Error.WriteLine("Connecting to DB");

            while (true)
            {
                try
                {
                    connection = new NpgsqlConnection(connectionString);
                    connection.Open();
                    break;
                }
                catch (SocketException e)
                {
                    Console.WriteLine("{0} Exception caught.", e);
                    Thread.Sleep(1000);
                }
                catch (DbException)
                {
                    Console.Error.WriteLine("Waiting for db - db error");
                    Thread.Sleep(1000);
                }
            }

            return connection;
        }

我有一个与官方Postgres容器不同的容器,我从命令

开始
docker run --name localpg -e POSTGRES_PASSWORD=MyPass -d postgres -p 5432:5432

现在我可以从pgAdmin与主机localhost,用户和密码postgres以及密码MyPass建立联系。

但是,如果我尝试使用命令docker run worker从同一台计算机上运行上面的.NET代码,我会遇到以下异常:

System.Net.Sockets.SocketException: Unknown error -1
   at Npgsql.NpgsqlConnector.Connect(NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnector.RawOpen(NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnector.Open(NpgsqlTimeout timeout)
   at Npgsql.ConnectorPool.Allocate(NpgsqlConnection conn, NpgsqlTimeout timeout)
   at Npgsql.NpgsqlConnection.OpenInternal()
   at Worker.Program.OpenDbConnection(String connectionString) Exception caught.

有什么想法吗?

修改

遵循Dan的建议我将连接字符串更改为

var pgsql = OpenDbConnection("Server=localpg;Database=postgres;Username=postgres;Password=MyPass;Port=5432");

但仍无效(InternalSocketException: No such device or address)。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
ad8fa68b5dab        bridge              bridge              local
984027aadc2a        host                host                local
5604001734fa        none                null                local

使用docker run worker启动应用容器(不使用撰写)。

1 个答案:

答案 0 :(得分:3)

每个容器都有自己的localhost

这里有两个容器,一个运行.Net应用程序,另一个运行Postgres数据库。从您的.Net应用程序容器的角度来看,本地主机(.Net容器)上没有运行Postgres,但您正在尝试连接到localhost:

var pgsql = OpenDbConnection("Server=localhost;Database=postgres; ...");

您的两个容器是分开的,每个容器都有自己的 localhost。要连接到Postgres容器,请使用其名称,就好像它是主机名一样。根据您在问题中发布的docker run命令判断,您应该使用:

var pgsql = OpenDbConnection("Server=localpg;Database=postgres; ...");

您的电脑也有自己的本地主机

您可以使用pgAdmin在localhost:5432上连接到Postgres的原因是您已将端口5432从Docker导出到外部主机(运行Docker的计算机)。这就是-p 5432:5432docker run命令中正在做的事情。

在该系统的localhost上,端口5432绑定到容器中的Postgres。 (这是第三个本地主机,与每个容器内部的localhost分开。)