skip to Main Content

I start 3 container:

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

Doing docker ps shows:
enter image description here

Then I exec into web:

docker exec -it web bash

Then I install psycopg2:

$ pip install psycopg2

Then I try to connect to the host: postgres, port:5432, database:hi:

I start python:

$ python

Then I run these commands:

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

And I get the following error:

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

I thought it might be a docker network issue, so I went to inspect it, and all the hostnames are there:

{
    "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": {}
}

It seems that the hostname postgres should be resolved to the ip of 172.17.0.3.

When I do that in python, it works:

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

How can I connect to the container named postgres using the its name as a host?

2

Answers


  1. Chosen as BEST ANSWER

    Seems like the issue is that all the containers were connecting to the default bridge network, which only allows resolution by IP address. Documentation:

    Containers on the default bridge network can only access each other by IP addresses, unless you use the --link option, which is considered legacy.

    For resolution by service name, I need to create my own network first, and then connect all the containers to the network.

    On a user-defined bridge network, containers can resolve each other by name or alias

    The commands should have been

    docker network create 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
    

  2. You are right in suspecting that this is a docker network issue.

    As you discovered, name resolution does not work with the default network being used. To allow for name resolution to work, you’ll need to use a separate network like so:

    docker network create my-network
    

    Then, run your containers with the --net argument:

    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
    

    Using this user-created network will then allow you to use the container names:

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

    Note that for setups using multiple containers I would recommend to use docker-compose instead of just docker commands, where this network is set up in the background for you.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search