无法使用 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 && 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 行,在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 [重复]