docker compose django应用程序找不到postgresql数据库

docker compose django应用程序找不到postgresql数据库,django,postgresql,docker,docker-compose,Django,Postgresql,Docker,Docker Compose,我正在尝试在docker容器中创建Django应用程序。该应用程序将使用一个带有postgis扩展的postgres db,我在另一个数据库中使用了它。我试图用docker compose解决这个问题,但无法让它工作 我可以让应用程序在没有容器的情况下工作,数据库容器化也很好。我还可以使用sqlite db使应用程序在容器中工作(因此包含的文件没有外部容器依赖项)。不管我做什么,它都找不到数据库 我的docker撰写文件: version: '3.7' services: postgi

我正在尝试在docker容器中创建Django应用程序。该应用程序将使用一个带有postgis扩展的postgres db,我在另一个数据库中使用了它。我试图用docker compose解决这个问题,但无法让它工作

我可以让应用程序在没有容器的情况下工作,数据库容器化也很好。我还可以使用sqlite db使应用程序在容器中工作(因此包含的文件没有外部容器依赖项)。不管我做什么,它都找不到数据库

我的docker撰写文件:

version: '3.7'

services:
    postgis:
        image: kartoza/postgis:12.1
        volumes:
            - postgres_data:/var/lib/postgresql/data/
        ports:
            - "${POSTGRES_PORT}:5432"
        environment:
            - POSTGRES_USER=${POSTGRES_USER}
            - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
            - POSTGRES_DB=${POSTGRES_DB}
        env_file:
            - .env
    web:
        build: .
#        command: sh -c "/wait && python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
        command: sh -c "python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
#        restart: on-failure
        ports:
            - "${APP_PORT}:8000"
        volumes:
            - .:/code
        depends_on:
            - postgis
        env_file:
            - .env
        environment:
            WAIT_HOSTS: 0.0.0.0:${POSTGRES_PORT}
volumes:
    postgres_data:
        name: ${POSTGRES_VOLUME}
我的Dockerfile(应用程序的):

My.env文件:

# POSTGRES
POSTGRES_PORT=25432
POSTGRES_USER=username
POSTGRES_PASSWORD=pass
POSTGRES_DB=db
POSTGRES_VOLUME=data
POSTGRES_HOST=localhost

# GEOSERVER


# DJANGO
APP_PORT=8000
最后是django应用程序的my settings.py中的my:

DATABASES = {
    'default': {
        'ENGINE': 'django.contrib.gis.db.backends.postgis',
        'NAME': os.getenv('POSTGRES_DBNAME'),
        'USER': os.getenv('POSTGRES_USER'),
        'PASSWORD': os.getenv('POSTGRES_PASS'),
        'HOST': os.getenv("POSTGRES_HOST", "localhost"),
        'PORT': os.getenv('POSTGRES_PORT')
    }
}
我已经尝试了很多东西(正如你在一些评论中看到的)。我意识到docker compose似乎不会等到postgres完全启动、旋转并接受请求,所以我尝试构建一个等待功能(如网站上建议的)。我首先进行了迁移,并在Dockerfile中运行服务器(在构建过程中进行迁移,并将runserver作为启动命令),但这需要postgres,因为它没有等待,所以无法正常工作。我最后把它全部放到docker-compose.yml文件中,但仍然无法让它工作

我得到的错误是:

web_1      |    Is the server running on host "localhost" (127.0.0.1) and accepting
web_1      |    TCP/IP connections on port 25432?
web_1      | could not connect to server: Cannot assign requested address
web_1      |    Is the server running on host "localhost" (::1) and accepting
web_1      |    TCP/IP connections on port 25432?

有人知道这为什么不起作用吗?

您不能对docker容器使用localhost,它将指向容器本身,而不是容器的主机。而是切换到使用服务名称

要解决此问题,请将环境更改为

# POSTGRES
POSTGRES_PORT=5432
POSTGRES_USER=username
POSTGRES_PASSWORD=pass
POSTGRES_DB=db
POSTGRES_VOLUME=data
POSTGRES_HOST=postgis

# DJANGO
APP_PORT=8000
然后你就可以把这个文件

version: '3.7'

services:
    postgis:
        image: kartoza/postgis:12.1
        volumes:
            - postgres_data:/var/lib/postgresql/data/
        environment:
            - POSTGRES_USER=${POSTGRES_USER}
            - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
            - POSTGRES_DB=${POSTGRES_DB}
        env_file:
            - .env
    web:
        build: .
#        command: sh -c "/wait && python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
        command: sh -c "python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
#        restart: on-failure
        ports:
            - "${APP_PORT}:8000"
        volumes:
            - .:/code
        depends_on:
            - postgis
        env_file:
            - .env
        environment:
            WAIT_HOSTS: postgis:${POSTGRES_PORT}
volumes:
    postgres_data:
        name: ${POSTGRES_VOLUME}

不能对docker容器使用localhost,它将指向容器本身,而不是容器的主机。而是切换到使用服务名称

要解决此问题,请将环境更改为

# POSTGRES
POSTGRES_PORT=5432
POSTGRES_USER=username
POSTGRES_PASSWORD=pass
POSTGRES_DB=db
POSTGRES_VOLUME=data
POSTGRES_HOST=postgis

# DJANGO
APP_PORT=8000
然后你就可以把这个文件

version: '3.7'

services:
    postgis:
        image: kartoza/postgis:12.1
        volumes:
            - postgres_data:/var/lib/postgresql/data/
        environment:
            - POSTGRES_USER=${POSTGRES_USER}
            - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
            - POSTGRES_DB=${POSTGRES_DB}
        env_file:
            - .env
    web:
        build: .
#        command: sh -c "/wait && python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
        command: sh -c "python manage.py migrate --no-input && python /code/app/manage.py runserver 0.0.0.0:${APP_PORT}"
#        restart: on-failure
        ports:
            - "${APP_PORT}:8000"
        volumes:
            - .:/code
        depends_on:
            - postgis
        env_file:
            - .env
        environment:
            WAIT_HOSTS: postgis:${POSTGRES_PORT}
volumes:
    postgres_data:
        name: ${POSTGRES_VOLUME}

我在django应用程序的
settings.py
中看到,您通过

'HOST': os.getenv("POSTGRES_HOST", "localhost"),
.env
中,将的值设置为
POSTGRES\u HOST
localhost
。这意味着
web
容器正试图到达本地主机上的Postgres服务器
postgis
,但实际情况并非如此

为了解决此问题,只需将
.env
文件更新如下:

POSTGRES_PORT=5432
...
POSTGRES_HOST=postgis
...
原因是在您的案例中,
docker compose
在同一docker网络中带来了两个容器:
postgis
web
,它们可以通过各自的DNS名称(即
postgis
web
)相互联系


关于端口,
web
容器可以访问
postgis
端口
5432
但不能访问
25432
,而主机可以访问数据库端口
25432
但不能访问
5432
我看到在django应用程序的
设置.py
中,您是通过

'HOST': os.getenv("POSTGRES_HOST", "localhost"),
.env
中,将的值设置为
POSTGRES\u HOST
localhost
。这意味着
web
容器正试图到达本地主机上的Postgres服务器
postgis
,但实际情况并非如此

为了解决此问题,只需将
.env
文件更新如下:

POSTGRES_PORT=5432
...
POSTGRES_HOST=postgis
...
原因是在您的案例中,
docker compose
在同一docker网络中带来了两个容器:
postgis
web
,它们可以通过各自的DNS名称(即
postgis
web
)相互联系


关于端口,
web
容器可以到达
postgis
端口
5432
但不能
25432
,而主机可以到达数据库端口
25432
但不能
5432

我认为您的数据库主机应该是数据库容器的名称。因为在docker环境中,您可以使用容器名称在容器之间进行通信。尝试使用
postgis
作为数据库
HOST
为什么不将它们放到网络中?@SadanA。我曾尝试在django设置中,在docker compose文件(环境:WAIT_HOSTS:postgis:${POSTGRES_PORT})中使用postgis,可惜没有用。安德烈·内鲁宾:我会调查网络,好主意。我认为你的数据库主机应该是数据库容器的名称。因为在docker环境中,您可以使用容器名称在容器之间进行通信。尝试使用
postgis
作为数据库
HOST
为什么不将它们放到网络中?@SadanA。我曾尝试在django设置中,在docker compose文件(环境:WAIT_HOSTS:postgis:${POSTGRES_PORT})中使用postgis,可惜没有用。安德烈·内鲁宾:将研究网络,好主意。谢谢你的评论,我仍然收到这样一条消息:web|1|是在主机“postgis”(192.168.192.2)上运行的服务器,并且在端口25432上接受web|1|TCP/IP连接吗?谢谢你的评论,我仍然收到这样一条消息:web|1|是在主机“postgis”上运行的服务器(192.168.192.2)并在端口25432上接受web|1 | TCP/IP连接?我不完全理解,我正在使用docker compose文件在单独的容器中运行postgres,这是建议号1。我没有在mac上本地安装postgres。我更改了代码(in.env postgres|U主机现在是postgis),它仍然不起作用。但我会在OP中更新我的代码以反映变化。我已经更新了我的答案。
POSTGRES\u端口
需要是
5432
谢谢,我终于让它起作用了。我没有意识到内部端口被其他容器使用,而外部端口可以在网络之外使用。我不完全理解d、 我正在使用docker compose文件在单独的容器中运行postgres,这是建议1。我没有在mac上本地安装postgres。我已经更改了代码(in.env postgres_HOST现在是postgis),它仍然不起作用。但我将在