无法从已停靠的应用程序连接到docker中的postgres服务器

aiqt4smr  于 2021-09-08  发布在  Java
关注(0)|答案(3)|浏览(274)

我想运行一个Docked django应用程序和一个Docked postgres。
我通过以下方式运行Docked django应用程序:

docker run --rm --env-file /path/to/variables -d -p 8000:8000 django_app:test

我使用以下方法运行停靠的postgres:

docker run --rm -d --env-file /path/to/secrets/variables -p 5432:5432 \
    -v "$PWD/my-postgres.conf":/etc/postgresql/postgresql.conf \
    --mount src=/path/to/db/data,dst=/var/lib/postgresql/data,type=bind \
    postgres:alpine -c 'config_file=/etc/postgresql/postgresql.conf'

my postgres config是postgres docker容器文档中建议的默认配置。它本质上是一个包含 listen_addresses = '*' 我对两个容器使用相同的环境变量:

DJANGO_SETTINGS_MODULE=settings.module
PROJECT_KEY=xxyyzzabcdefg
DB_ENGINE=django.db.backends.postgresql
POSTGRES_DB=db_name
POSTGRES_USER=db_user
POSTGRES_PASSWORD=verydifficultpassword
POSTGRES_HOST=localhost # I've also tried to use 0.0.0.0
POSTGRES_PORT=5432

数据库的my django设置模块是:

DATABASES = {
    'default': {
        'ENGINE': os.environ.get('DB_ENGINE'),
        'NAME': os.environ.get('POSTGRES_DB'),
        'USER': os.environ.get('POSTGRES_USER'),
        'PASSWORD': os.environ.get('POSTGRES_PASSWORD'),
        'HOST': os.environ.get('POSTGRES_HOST'),
        'PORT': os.environ.get('POSTGRES_PORT')
        }
  }

然而,我不断得到:

django.db.utils.OperationalError: could not connect to server: Connection refused
    Is the server running on host "0.0.0.0" and accepting
    TCP/IP connections on port 5432?

my django应用程序的DockerFile如下所示:

FROM python:alpine3.7
COPY --from=installer /app /app

# required for postgres

COPY --from=installer /usr/lib /usr/lib
COPY --from=installer /usr/local/bin /usr/local/bin
COPY --from=installer /usr/local/lib /usr/local/lib
ARG SETTINGS_MODULE
WORKDIR /app
ENTRYPOINT python manage.py migrate &&\
           python manage.py test &&\
           python manage.py create_default_groups &&\
           python manage.py set_screen_permissions &&\
           python manage.py create_test_users &&\
           python manage.py init_core &&\
           python manage.py runserver 0.0.0.0:8000

另一个有趣的事实是,如果我在本地运行应用程序 python manage.py runserver 当postgres容器运行时,应用程序似乎正在运行。
有人能帮我弄清楚为什么我的连接被拒绝了吗?提前谢谢!

8nuwlpux

8nuwlpux1#

只需使用用户定义的网桥网络。首先,通过阅读docker中不同类型网络的简短说明,充分利用您的知识:https://docs.docker.com/network/bridge/
其次,定义自己的网络

docker network create foo

接下来,运行连接到此网络的容器:

docker run --rm --env-file /path/to/variables -d --network foo django_app:test
docker run --rm -d ... --network foo postgres:alpine ...

请注意这两个命令 --network foo . 此外,在这种情况下,您不需要公开端口—在用户定义的网络中,它是自动完成的:
连接到同一用户定义网桥网络的容器会自动将所有端口彼此公开,而不会向外部世界公开任何端口。这使得容器化应用程序可以轻松地相互通信,而不会意外地打开对外部世界的访问。
第三,为容器提供人类可读的主机名 --name bar ```
docker run ... --network foo --name my-django django_app:test ...
docker run ... --network foo --name my-postgres postgres:alpine ...

最后修复连接字符串-从 `localhost` 到容器名称,如 `my-postgres` :

...
POSTGRES_HOST=my-postgres
...

muk1a3rh

muk1a3rh2#

在使用django的docker容器中,本地主机上没有运行postgres。您需要通过指定容器名称而不是localhost来指向postgres docker容器。此外,postgres容器和您的应用程序必须位于同一网络中。看见https://docs.docker.com/network/
要创建网络运行,请执行以下操作:

docker network create --driver bridge my-network

要在网络中运行docker容器,请使用:

docker run --network my-network -it container_name

要使用django在容器中设置postgres,请执行以下操作:

POSTGRES_HOST=postgres-container-name
v7pvogib

v7pvogib3#

在您的情况下,您没有指定容器名称。设置时 POSTGRES_HOST=localhost 您正在告诉django容器连接到自身。这自然会失败,因为django容器中没有postgres服务器。
您的两个容器正在使用默认值 bridge 网络(docker0)。在网桥网络中,容器名称用作主机名。
这意味着从你的 django 您可以访问 postgres 容器的名称作为主机名。
要从django应用程序连接到postgres,您需要:
使用 --name option . 例子: docker run --rm --name mypostgresdb -d ... postgres:alpine -c ... 首先创建postgres容器并等待它启动。然后创建数据库和用户/密码。
仅当postgres启动时,才创建django容器。如果postgres容器未启动,django容器将失败,因为它正试图在入口点运行迁移。
这个 POSTGRES_HOST django容器中的env变量应接收postgres容器的名称作为值。例子: POSTGRES_HOST=mypostgresdb 要检查与postgres容器的连接,可以从django容器ping它。

相关问题