繁体   English   中英

Docker:当使用容器名称从一个容器连接到另一个容器时,如何修复“无法将主机名”postgres“转换为地址”?

[英]Docker: How to fix “could not translate host name ”postgres“ to address” when connecting from one container to another using container name?

我启动 3 个容器:

docker run -d --rm --name redis    --publish 6379:6379 redis 
docker run -d --rm --name postgres --publish 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=hi postgres:9.6
docker run -d --rm --name web      --publish 8000:8000 python:3.6.8-stretch sleep 1000

docker ps显示: 在此处输入图像描述

然后我执行到web

docker exec -it web bash

然后我安装psycopg2

$ pip install psycopg2

然后我尝试连接到host: postgresport:5432database:hi

我启动 python:

$ python

然后我运行这些命令:

import psycopg2
conn = psycopg2.connect(host="postgres", port = 5432, database="hi", user="postgres", password="<passwd>")

我收到以下错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/psycopg2/__init__.py", line 127, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "postgres" to address: Name or service not known

我以为可能是 docker 网络问题,所以我去检查它,所有主机名都在那里:

{
    "Name": "bridge",
    "Id": "8e37606d20ae80189da4d7ecdb7673274fa2e0c9dd2b5c2b4c3db4e545c1ef20",
    "Created": "2020-05-14T19:10:43.532158344Z",
    "Scope": "local",
    "Driver": "bridge",
    "EnableIPv6": false,
    "IPAM": {
        "Driver": "default",
        "Options": null,
        "Config": [
            {
                "Subnet": "172.17.0.0/16",
                "Gateway": "172.17.0.1"
            }
        ]
    },
    "Internal": false,
    "Attachable": false,
    "Ingress": false,
    "ConfigFrom": {
        "Network": ""
    },
    "ConfigOnly": false,
    "Containers": {
        "3bb2a6cf4fbb235324d335f238c20fe026e37bccc717d1cd0bd1df43e70dbec6": {
            "Name": "redis",
            "EndpointID": "f927fc2a199d033bbbc8ecc8ff1bccf508e607384e4820884f3236f11a961c04",
            "MacAddress": "02:42:ac:11:00:02",
            "IPv4Address": "172.17.0.2/16",
            "IPv6Address": ""
        },
        "545065d96fb6f867724ece2cf11881af26be9885f16212bef4260bccba00a2be": {
            "Name": "web",
            "EndpointID": "750133a6bb72e23929c57f32aa7776bc85d3dd255a16473a4afe230d0c6cb9c2",
            "MacAddress": "02:42:ac:11:00:04",
            "IPv4Address": "172.17.0.4/16",
            "IPv6Address": ""
        },
        "cfb2e556ca9f26ff8c7063f2347b81b2a90365cfa476cab8611edf1586404a88": {
            "Name": "postgres",
            "EndpointID": "069411d5c42b3b968ce38b92b7122c608f1dca696517122728f23086fdce53c7",
            "MacAddress": "02:42:ac:11:00:03",
            "IPv4Address": "172.17.0.3/16",
            "IPv6Address": ""
        }
    },
    "Options": {
        "com.docker.network.bridge.default_bridge": "true",
        "com.docker.network.bridge.enable_icc": "true",
        "com.docker.network.bridge.enable_ip_masquerade": "true",
        "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
        "com.docker.network.bridge.name": "docker0",
        "com.docker.network.driver.mtu": "1500"
    },
    "Labels": {}
}

似乎主机名postgres应该解析为172.17.0.3ip

当我在 python 中这样做时,它可以工作:

import psycopg2
conn = psycopg2.connect(host="172.17.0.3", port = 5432, database="hi", user="postgres", password="")

如何使用名称作为主机连接到名为postgres的容器?

您怀疑这是 docker 网络问题是正确的。

正如您所发现的,名称解析不适用于正在使用的默认网络。 为了允许名称解析工作,您需要使用单独的网络,如下所示:

docker network create my-network

然后,使用--net参数运行您的容器:

docker run -d --rm --name postgres --publish 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=hi --net my-network postgres:9.6
docker run -d --rm --name redis --publish 6379:6379 --net my-network redis
docker run -d --rm --name web --publish 8000:8000 --net my-network python:3.6.8-stretch sleep 1000

然后,使用此用户创建的网络将允许您使用容器名称:

>>> import psycopg2
>>> conn = psycopg2.connect(host="postgres", port = 5432, database="hi", user="postgres", password="")
>>> conn.info.user
'postgres'

请注意,对于使用多个容器的设置,我建议使用docker-compose而不仅仅是docker命令,该网络是在后台为您设置的。

似乎问题在于所有容器都连接到默认桥接网络,该网络仅允许通过 IP 地址解析。 文档

默认桥接网络上的容器只能通过 IP 地址相互访问,除非您使用 --link 选项,该选项被视为旧版。

通过服务名称解析,我需要先创建自己的网络,然后将所有容器连接到网络。

在用户定义的桥接网络上,容器可以通过名称或别名相互解析

命令应该是

docker create network my-network

docker run -d --rm --network my-network --name redis    --publish 6379:6379 redis 
docker run -d --rm --network my-network --name postgres --publish 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust -e POSTGRES_DB=hi postgres:9.6
docker run -d --rm --network my-network --name web      --publish 8000:8000 python:3.6.8-stretch sleep 1000

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM