Django с БД postgreSQL на Docker - django.db.utils.OperationalError: could not connect to server: Connection refused
Я следую этому учебнику по "докеризации" Django + PgSQL + gunicorn + nginx .
Релевантная информация
- ОС хост-машины - Ubuntu 20.0.4 LTS
- Docker-desktop: Docker версии 20.10.16, сборка aa7e414 .
Вот моя установка на данный момент:
(соответствующие части) 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.
Я бы все же рекомендовал использовать первый подход.