无法使用 Postgres、Docker Compose 和 Psycopg2 将主机名“db”转换为地址

Posted

技术标签:

【中文标题】无法使用 Postgres、Docker Compose 和 Psycopg2 将主机名“db”转换为地址【英文标题】:Could not translate host name "db" to address using Postgres, Docker Compose and Psycopg2 【发布时间】:2019-01-15 22:57:34 【问题描述】:

在一个文件夹中,我有 3 个文件:base.py、Dockerfile 和 docker-compose.yml。

base.py:

import psycopg2

conn = psycopg2.connect("dbname='base123' user='postgres' host='db' password='pw1234'")

Dockerfile:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -y install python-pip
RUN apt-get update
RUN pip install --upgrade pip
RUN pip install psycopg2-binary

COPY base.py base.py

RUN python base.py

docker-compose.yml:

version: '3'
services:
  db:
    image: 'postgres:latest'
    expose:
      - "5432"
    environment:
      POSTGRES_PASSWORD: pw1234
      POSTGRES_DB: base123
  aprrka:
    build: .    
    depends_on:
      - db

运行docker-compose up后,出现以下错误:

Traceback (most recent call last):
  File "base.py", line 5, in <module>
conn = psycopg2.connect("dbname='base123' user='postgres' host='db' password='pw1234'")
   File "/usr/local/lib/python2.7/dist-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Name or service not known

ERROR: Service 'aprrka' failed to build: The command '/bin/sh -c python base.py' returned a non-zero code: 1

我不知道为什么会出现此错误。我暴露了 5432 端口。默认情况下,Compose 为应用程序设置了一个网络。每个服务都加入默认网络,我认为我的应用程序与 postgres 应该一起工作。我写错了 docker-compose.yml 吗?

【问题讨论】:

jack-gore 的回答解决了您的问题。诊断的一种方法可能是使用已知良好的第二个容器来访问db。请参阅 docs.docker.com 上的映像文档以及 adminer 映像 (docs.docker.com/samples/library/postgres/…) 的使用。其次,Dockerfile 将受益于通过减少RUN 命令的数量来减少创建的层数。例如RUN apt-get update &amp;&amp; apt-get -y install python-pip(你不需要最后的apt-get update)。 【参考方案1】:

问题是您不应该将python base.py 作为RUN 指令的一部分运行。

RUN 指令仅在您构建映像时执行。 postgres 容器此时没有运行,也没有创建网络。相反,您想使用 CMD 指令。

Dockerfile改成这样:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -y install python-pip
RUN apt-get update
RUN pip install --upgrade pip
RUN pip install psycopg2-binary

COPY base.py base.py

CMD ["python", "base.py"]

以上应该会导致解析主机名db。但是,如果您的 python 代码没有任何用于连接到数据库的重新连接逻辑,则容器可能仍然会出错。这是因为 postgres 容器将运行,但数据库不会准备好接受连接。

可以通过将restart: always 添加到您的docker-compose.yml 来临时解决此问题。

version: '3'
services:
  db:
    image: 'postgres:latest'
    expose:
      - "5432"
    environment:
      POSTGRES_PASSWORD: pw1234
      POSTGRES_DB: base123
  aprrka:
    restart: always
    build: .    
    depends_on:
      - db

希望这能让您启动并运行。

【讨论】:

谢谢!很难过,但我仍然不知道如何解决下一个错误。 aprrka_1 |回溯(最后一次调用):文件“base.py”,第 5 行,在 中 conn = psycopg2.connect("dbname='base123' user='postgres' host='db' password='pw1234'" ) 文件“/usr/local/lib/python2.7/dist-packages/psycopg2/__init__.py”,第 130 行,在 connect conn = _connect(dsn, connection_factory=connection_factory, **kwasync) psycopg2.OperationalError: could not连接到服务器:连接被拒绝服务器是否在主机“db”(172.20.0.2)上运行并接受端口 5432 上的 TCP/IP 连接? 这个错误是我回答的第二部分试图修复的。您需要在代码中添加重新连接逻辑,将restart: always 添加到您的撰写文件中。你试过吗? 是的,我做到了。它可以工作,但是第一次尝试连接到 db 是不成功的。我是否需要在我的 base.py 文件中输入一些“等待时间”才能正确连接而不会出错?我想这对我的整个 Docker 映像来说不会“更好”,但是看看它是如何运行的会更好。我的解决方案正确吗? 是的,这是一个单独的问题,但您想在代码中实现某种等待机制。【参考方案2】:

在 docker compose 文件中的同一网络上添加数据库和 Web 服务。也可以链接 db 服务并在启动 db 服务后启动 web 服务。

在docker compose文件中正确添加network、link和depends_on配置后问题将得到修复。

配置示例:

  services:
      db:
          container_name: db
          networks:
              - djangonetwork
      web:
          depends_on:
             - db
          links:
             - db:db
          networks:
             - djangonetwork

  networks:
      djangonetwork:
          driver: bridge

在我的 docker compose 文件中,我使用网络名称作为“djangonetwork”,您可以使用任何其他名称。

以上配置帮助我解决了“无法翻译主机名数据库”的问题。

【讨论】:

好吧,开枪。这对我来说刚刚完成。谢谢。 哇,终于搞定了!谢谢!【参考方案3】:

如果您使用 docker-compose,请先将此行添加到您的 .yml:

environment:
  - "POSTGRES_HOST_AUTH_METHOD=trust"

之后你只启动你的 db docker:

docker-compose up db

它应该以如下消息正常开始:

Recreating db... done
Attaching to db
db_1           | ********************************************************************************
db_1           | WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow
db_1           |          anyone with access to the Postgres port to access your database without
db_1           |          a password, even if POSTGRES_PASSWORD is set. See PostgreSQL
db_1           |          documentation about "trust":
db_1           |          https://www.postgresql.org/docs/current/auth-trust.html
db_1           |          In Docker's default configuration, this is effectively any other
db_1           |          container on the same system.
db_1           | 
db_1           |          It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace
db_1           |          it with "-e POSTGRES_PASSWORD=password" instead to set a password in
db_1           |          "docker run".
db_1           | ********************************************************************************

【讨论】:

【参考方案4】:

如果您将其添加到 docker-compose.yml 中的数据库容器中,它应该可以解决问题

environment:
  - "POSTGRES_HOST_AUTH_METHOD=trust"

【讨论】:

这也会让你的数据库变得不安全。【参考方案5】:

另一种可能的情况,

检查端口是否已被其他 docker 容器使用。 使用命令:

$ docker container ls --format "table .ID\t.Names\t.Ports" -a

然后在 docker-compose 文件中更改您的端口/公开

【讨论】:

【参考方案6】:

我想我会给出一个更新的答案,因为我最近发现了一个类似的问题。

我有一个类似的设置,应用程序可以从本地运行的 docker 正确连接,但在 Jenkins 中运行时会失败。

image: postgres:latest 更改为image: postgres:13.4-alpine 解决了这个问题。

【讨论】:

以上是关于无法使用 Postgres、Docker Compose 和 Psycopg2 将主机名“db”转换为地址的主要内容,如果未能解决你的问题,请参考以下文章

节点服务器无法通过 Docker 连接到 Postgres,使用 TypeORM

Django 无法在 Docker 设置中连接到 Postgres

无法从 docker-compose 启动 postgres docker 容器

docker-compose spring boot无法连接到Postgres [重复]

docker postgres 无法更改 pgdata 权限

无法在 docker-compose 中使用 Postgres DB - ECONNREFUSED