【问题标题】:psycopg2 can’t connect to postgres database in dockerized Python-Flask apppsycopg2 无法连接到 dockerized Python-Flask 应用程序中的 postgres 数据库
【发布时间】:2019-11-17 08:02:26
【问题描述】:

我正在开发一个 Python-Flask 项目,该项目有一个用于 web 应用程序的 docker 容器和另一个用于 postgres 数据库的 docker 容器。我使用 virtualenv 来管理我的所有依赖项。在安装psycopg2 时遇到一些初始问题后,我现在已经安装了所有依赖项。 但是,每当我尝试从命令行运行flask db migrate 时,都会收到psycopg2 错误。从下面的错误中查看一个 sn-p:

File "/home/myuser/Workspace/GroupName/MyApp/env/lib/python3.7/site-packages/psycopg2/__init__.py", line 126, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "postgres" to address: Temporary failure in name resolution


The above exception was the direct cause of the following exception:
  File "/home/myuser/Workspace/GroupName/MyApp/env/lib/python3.7/site-packages/psycopg2/__init__.py", line 126, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) could not translate host name "postgres" to address: Temporary failure in name resolution

这是我的docker-compose.yml

services:
 postgres:
   restart: always
   image: postgres:latest
   environment:
     POSTGRES_USER: MyApp
     POSTGRES_PASSWORD: fakepassword
     POSTGRES_DB: MyApp-dev
   volumes:
     - ./container_data/postgres:/var/lib/postgresql/data
   ports:
     - "5432:5432"

 web:
   restart: always
   build:
      context: .
      args:
      - DOCKER_BUILD_ENV
      dockerfile: ./dockerfiles/web/Dockerfile
   environment:
     AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}"
     AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}"
     AWS_DEFAULT_REGION: "${AWS_DEFAULT_REGION}"
     S3_BUCKET_NAME: "${S3_BUCKET_NAME}"
     APPROVE_REGISTRATIONS: "${APPROVE_REGISTRATIONS}"
     FLASK_APP: app
     FLASK_ENV: "${FLASK_ENV:-development}"
   volumes:
     - ./MyApp/:/usr/src/app/MyApp/:z
   links:
     - postgres:postgres
   expose:
     - "3000"
   command: scripts/entrypoint.sh
   ports:
     - "3000:3000"

以下是与requirements.txt 和数据库相关的dockerfile 的摘录。

.....
RUN pip3 install --no-cache-dir virtualenv
RUN virtualenv /ve
ENV PATH=/ve/bin:$PATH
........

USER www-data

COPY requirements.txt dev-requirements.txt /usr/src/app/
RUN pip3 install --no-cache-dir -r requirements.txt

ARG DOCKER_BUILD_ENV
RUN test "${DOCKER_BUILD_ENV}" = production || pip3 install --no-cache-dir -r dev-requirements.txt

CMD ["/bin/bash"]
COPY package.json /usr/src/app/
RUN yarn

COPY create_db.py test_data.py /usr/src/app/
EXPOSE 3000

ENV PATH="/usr/src/app/geckodriver:${PATH}"
ENV SECRET_KEY *************
ENV SQLALCHEMY_DATABASE_URI postgresql://MyApp:fakepassword@postgres/MyApp-dev

WORKDIR /usr/src/app/MyApp

CMD ["scripts/entrypoint.sh"]

这里是entrypoint.sh。我认为这不会导致错误,因为我在从命令行而不是从该脚本运行 flask db migrate 时遇到了错误。

#!/bin/bash
if [ "${DOCKER_BUILD_ENV:-}" == "production" ]; then
    flask run --host=0.0.0.0 --port=3000
else
    yarn build
    yarn watch &
    flask run --host=0.0.0.0 --port=3000
fi

我查找了类似的问题,例如 psycopg2 can't see my PostgreSQL instance,但我的代码中没有任何地方明确使用 psycopg2 来创建连接。最接近的是models.py 的顶部,我放的地方:

db = SQLAlchemy()

我运行docker ps 并确认这两个服务都在运行。

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
a1e6891161d1        myapp_web   "scripts/entrypoint.…"   57 minutes ago      Up 57 minutes       0.0.0.0:3000->3000/tcp   myapp_web_1
bfa83d282ac7        postgres:latest     "docker-entrypoint.s…"   2 weeks ago         Up 57 minutes       0.0.0.0:5432->5432/tcp   myapp_postgres_1

任何想法为什么我在 virtualenv 中时无法从命令行运行 flask db migrateflask db stamp head

【问题讨论】:

  • 你能把这个减少到一个minimal reproducible example来证明这个问题吗?例如,将 Dockerfile 缩减到最低限度以安装应用程序(而不是额外的 Web 浏览器或 Node 构建链),但要包含诸如 entrypoint.sh 脚本之类的内容,该脚本会显示您尝试运行 flask db migrate 的位置。
  • @DavidMaze 当然,我会减少问题中的信息。在 StackOverflow 上提问时,我尝试包含尽可能多的信息,部分原因是我之前因包含不包含 import 语句的代码 sn-ps 而受到谴责。但是,我意识到人们更容易阅读较短的问题。
  • 我认为问题出在连接细节上。您确定主机名是“postgres”而不是“locahost”吗?

标签: postgresql docker flask sqlalchemy psycopg2


【解决方案1】:

docker-library/postgres GitHub issues #681 中报告了导致此问题的重大更改。我的解决方案是按照 docker logs 中的说明进行操作:

   Error: Database is uninitialized and superuser password is not specified.
   You must specify POSTGRES_PASSWORD for the superuser. Use
   "-e POSTGRES_PASSWORD=password" to set it in "docker run".

   You may also use POSTGRES_HOST_AUTH_METHOD=trust to allow all connections
   without a password. This is *not* recommended. See PostgreSQL
   documentation about "trust":
   https://www.postgresql.org/docs/current/auth-trust.html

在docker compose中,我添加了如下环境变量:

  postgres:
    restart: always
    image: postgres:latest
    environment:
      POSTGRES_HOST_AUTH_METHOD=trust
    ports:
      - "5432:5432"

后一个环境变量允许任何人连接到数据库,因此建议设置密码,因为这是一种不安全的解决方法。

【讨论】:

    猜你喜欢
    • 2021-03-07
    • 2022-12-13
    • 1970-01-01
    • 2019-12-14
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 1970-01-01
    相关资源
    最近更新 更多