Django с БД postgreSQL на Docker - django.db.utils.OperationalError: could not connect to server: Connection refused

Я следую этому учебнику по "докеризации" Django + PgSQL + gunicorn + nginx .

Релевантная информация

  1. ОС хост-машины - Ubuntu 20.0.4 LTS
  2. Docker-desktop: Docker версии 20.10.16, сборка aa7e414
  3. .

Вот моя установка на данный момент:

(соответствующие части) settings.py

import os

from pathlib import Path
from decouple import config
import dj_database_url

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=lambda v: [s.strip() for s in v.split(',')])


# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DATABASE_NAME'),
        'USER': config('DB_USER_NAME'),
        'PASSWORD': config('DB_USER_PWD'),
        'HOST': config('DB_HOST'),
        'PORT': config('DB_PORT'),
    }
}

# required for db to work on Heroku
db_from_env = dj_database_url.config(conn_max_age=600)
DATABASES['default'].update(db_from_env)

my-django-proj/my-django-proj/.env

ALLOWED_HOSTS=0.0.0.0,localhost,127.0.0.1,www.example.com,example.com,example.herokuapp.com

# Docker compose seems to need this
DJANGO_ALLOWED_HOSTS=localhost 127.0.0.1 [::1]

DEBUG=True

DATABASE_NAME=thedbname
DB_USER_NAME=myusername
DB_USER_PWD=thepassword
DB_HOST=localhost
DB_PORT=5432

Dockerfile

# pull official base image
FROM python:3.9.6-alpine

# set work directory
WORKDIR /usr/src/app

#############################
# set environment variables #
#############################

# Prevents Python from writing pyc files to disc (equivalent to python -B option)
ENV PYTHONDONTWRITEBYTECODE 1

# Prevents Python from buffering stdout and stderr (equivalent to python -u option)
ENV PYTHONUNBUFFERED 1


# install psycopg2 dependencies
RUN apk update \
    && apk add postgresql-dev gcc python3-dev musl-dev


# install dependencies
RUN pip install --upgrade pip
COPY ./my-django-proj/requirements.txt ./my-django-proj/
RUN pip install -r ./my-django-proj/requirements.txt

# copy project
COPY ./my-django-proj ./my-django-proj

compose.yml

services:
  web:
    build: .
    command: python my-django-proj/manage.py runserver 0.0.0.0:8000
    volumes:
      - ./my-django-proj/:/usr/src/app/my-django-proj/
    ports:
      - 8000:8000
    env_file:
      - ./my-django-proj/my-django-proj/.env

    depends_on:
      - db

  db:
    image: postgres:14.3-alpine

    restart: always
    container_name: postgres14_3
    #user: postgres

    ports:
      - 5432:5432    
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_USER=myusername
      - POSTGRES_PASSWORD=thepassword
      - POSTGRES_DB=thedbname


volumes:
  postgres_data:      

Выходной журнал из sudo docker compose up -d --build

postgres14_3  | 
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  starting PostgreSQL 14.3 on x86_64-pc-linux-musl, compiled by gcc (Alpine 11.2.1_git20220219) 11.2.1 20220219, 64-bit
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres14_3  | 2022-06-01 12:03:35.017 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres14_3  | 2022-06-01 12:03:35.022 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres14_3  | 2022-06-01 12:03:35.028 UTC [50] LOG:  database system was shut down at 2022-06-01 12:03:34 UTC
postgres14_3  | 2022-06-01 12:03:35.032 UTC [1] LOG:  database system is ready to accept connections

Вывод попытки миграции при запуске: sudo docker compose exec web python my-django-proj/manage.py migrate --noinput

Traceback (most recent call last):                                                                                                            
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 219, in ensure_connection                               
    self.connect()                                                                                                                            
  File "/usr/local/lib/python3.9/site-packages/django/utils/asyncio.py", line 26, in inner                                                    
    return func(*args, **kwargs)                                                                                                              
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 200, in connect                                         
    self.connection = self.get_new_connection(conn_params)                                                                                    
  File "/usr/local/lib/python3.9/site-packages/django/utils/asyncio.py", line 26, in inner                                                    
    return func(*args, **kwargs)                                                                                                              
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/postgresql/base.py", line 187, in get_new_connection                        
    connection = Database.connect(**conn_params)                                                                                              
  File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 122, in connect                                                    
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)                                                                    
psycopg2.OperationalError: could not connect to server: Connection refused                                                                    
        Is the server running on host "localhost" (127.0.0.1) and accepting                                                                   
        TCP/IP connections on port 5432?             

could not connect to server: Address not available
        Is the server running on host "localhost" (::1) and accepting
        TCP/IP connections on port 5432?

Поэтому я решил провести небольшое исследование на своей хост-машине

выход sudo netstat -tulpn | grep LISTEN

tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      118855/docker-proxy                                           
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1017/redis-server 1                                           
tcp        0      0 127.0.0.1:11211         0.0.0.0:*               LISTEN      934/memcached                                                 
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      754/systemd-resolve 
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      997/sshd: /usr/sbin 
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      72912/cupsd         
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      118727/docker-proxy 
tcp6       0      0 :::44543                :::*                    LISTEN      58417/code          
tcp6       0      0 :::8000                 :::*                    LISTEN      118862/docker-proxy 
tcp6       0      0 ::1:6379                :::*                    LISTEN      1017/redis-server 1 
tcp6       0      0 :::22                   :::*                    LISTEN      997/sshd: /usr/sbin 
tcp6       0      0 ::1:631                 :::*                    LISTEN      72912/cupsd         
tcp6       0      0 :::5432                 :::*                    LISTEN      118734/docker-proxy

PG очевидно работает на порту 5432 (поэтому сообщение Django вводит в заблуждение - я думаю). Я пытаюсь подключиться к Db на контейнере следующим образом:

sudo docker compose exec db psql -U myusername thedbname

psql (14.3) Введите "help" для получения справки.

thedbname=#

Итак, очевидно, что PG работает в контейнере - так что же вызывает отказ в подключении к Db? - и как мне это исправить, чтобы я мог запустить миграции и получить доступ к проекту Django на http://localhost:8000 на моей локальной машине?

Если вам не нужен доступ к postgres с вашего хоста, тогда нет необходимости в сопоставлении портов.

Контейнеры могут взаимодействовать вместе, поскольку они должны быть частью одной сети, используя имя службы, в вашем случае вы можете попробовать db, которое является именем вашего контейнера postgres вместо localhost.

Чтобы точно ответить на ваш вопрос, для доступа к хост-машине из контейнера docker вам нужно получить доступ к host.docker.internal. host.docker.internal будет указывать на ваш хост localhost.

Смотрите этот пост SO

Для Linux вам может потребоваться добавить:

extra_hosts:
    - "host.docker.internal:host-gateway"

к веб-сервису вашего docker-compose.

Я бы все же рекомендовал использовать первый подход.

Вернуться на верх