如何将 django 应用程序连接到 dockerized postgres db,从 dockerized django 和非 dockerized django 使用相同的 DATABASE_HOST

How to connect a django app to a dockerized postgres db, both from a dockerized django and non-dockerized django using same DATABASE_HOST

我有一个postgres容器,docker-compose.yml:

services:
  db:
    container_name: db
    expose:
      - "5432"
    ports:
      - 5432:5432
    volumes:
      - postgres_data:/var/lib/postgresql/data/

还有一个 django 项目 settings.py:

DATABASES = {
    'default': {
        'HOST': os.environ.get('POSTGRES_HOST', '127.0.0.1')
        # etc
    }
}

.env

POSTGRES_HOST_DJANGO=db

当我 运行 我的 django 应用程序在本地使用 manage.py runserver 0.0.0.0:8000 它连接正常,使用默认的 POSTGRES_HOST=127.0.0.1,因为 .env 不是未加载。

我有时也在容器中 运行 我的 django 应用程序:

docker-compose.yml:

   web:
    #restart: unless-stopped
    build: .
    env_file: .env
    command: bash -c "cd /app/src/ && python manage.py runserver 0.0.0.0:8000
    volumes: 
      - .:/app
    ports:
      - 8000:8000
    links: 
      - db:db

但是它使用 .env 文件并与 POSTGRES_HOST=db

连接

如果我尝试将本地 运行 django 应用程序与 POSTGRES_HOST=db 连接,它会失败:

django.db.utils.OperationalError: could not translate host name "db" to address: Name or service not known

如果我尝试 运行 容器中的 django 应用 POSTGRES_HOST=127.0.0.1,它也会以同样的方式失败。

我怎样才能让他们使用相同的 POSTGRES_HOST

问题似乎出在网络配置上。我一个都没看到。

docker-compose 的默认行为是它为每个撰写文件创建一个网络 - 默认情况下,名称是带有“_default”的文件夹名称。

Django App在不同的网络和Postgres在不同的网络

如果您的 Django 应用程序和您的 Postgres 容器位于不同的 docker-compose 文件中,则使用容器名称解析主机将不起作用(默认情况下,可以使用自定义网络配置来完成)在两个不同的网络中。

因为你已经完成了端口绑定,你可以通过在容器中提供主机的私有 ip 和端口 5432 来直接访问 Postgres,这种方式是通过主机网络进行通信。

如果您发现需要让容器直接相互通信,请确保它们在同一个 docker 网络上

我知道怎么做了。这不是让他们使用相同的变量,而是让他们根据它的方式读取不同的变量 运行。所以:

docker-compose.yml

   web:
    build: .
    command: bash -c "cd /app/src/ && python manage.py runserver 0.0.0.0:8000
    env_file: .env
    environment:
      POSTGRES_HOST: db  # takes precendent over .env file

并且在 .env:

POSTGRES_HOST=127.0.0.1

现在,当我 运行 在本地使用 ./manage.py runserver 时,它使用 .env 文件并正确连接到位于 127.0.0.1:5342

的数据库容器

但是如果我 运行 docker-compose up web,即使它也读取 .env 文件,组合文件中提供的环境变量优先,它使用 POSTGRES_HOST: db 并连接到数据库容器也是如此!