如何将 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
并连接到数据库容器也是如此!
我有一个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
并连接到数据库容器也是如此!