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

问题描述 投票:0回答:7

在一个文件夹中,我有 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?

python postgresql docker docker-compose psycopg2
7个回答
42
投票

问题是您不应该将

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

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


26
投票

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

正确添加network、link和depends_on配置后,docker compose文件中的问题将得到解决。

配置示例:

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

  networks:
      djangonetwork:
          driver: bridge

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

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


11
投票

如果您使用 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           | ********************************************************************************

建议:这样做并不安全。 如果您决定使用此解决方案,请确保在 .gitignore 中列出您的 docker 文件,这样您就不会将其推入生产环境。


6
投票

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

environment:
  - "POSTGRES_HOST_AUTH_METHOD=trust"

0
投票

另一种可能的情况,

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

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

然后在 docker-compose 文件中更改端口/暴露


0
投票

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

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

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


0
投票

我检查了所有方法和解决方案,但无法解决问题。

docker文件: ` 来自 python:3.11.1-slim

工作目录/应用程序

ENV Python不写入字节码1 ENV Python 无缓冲 1

复制requirements.txt。 运行 pip install -rrequirements.txt

复制。 。 `

docker-compose.yml ` 应用程序: 建造: 。 命令: uvicorn app.main:app --host 0.0.0.0 --reload --workers 1 卷: - 。:/应用程序 环境: - DATABASE_URL=postgresql://postgres:S6ge9R53Ewn9SRtMZx@db/fastapi_app 依赖于取决于: - 分贝

ports:
  - 8008:8000

db:

image: postgres:15-alpine
networks:
  - BackendNetwork
volumes:
  - postgres_data:/var/lib/postgresql/data/
environment:
  - POSTGRES_USER=postgres
  - POSTGRES_PASSWORD=S6ge9R53Ewn9SRtMZx
  - POSTGRES_DB=fastapi_app
expose:
  - 5432

`

© www.soinside.com 2019 - 2024. All rights reserved.