Получил django.db.utils.OperationalError: не удалось подключиться к серверу: соединение отклонено

Вопрос или проблема

Я нашел проект Django и не смог запустить его в контейнере Docker следующим образом:

  1. git clone https://github.com/NAL-i5K/django-blast.git
  2. $ cat requirements.txt в этом файле необходимо обновить следующие зависимости:
    • psycopg2==2.8.6

У меня есть следующий Dockerfile:

FROM python:2
ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y postgresql-client
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
RUN mkdir -p /var/log/django
RUN mkdir -p /var/log/i5k

Для docker-compose.yml я использую:

version: "3"

services:
  db:
    image: postgres
    volumes:
      - ./data/db:/var/lib/postgresql/data
      - ./scripts/install-extensions.sql:/docker-entrypoint-initdb.d/install-extensions.sql

    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres

  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - "8000:8000"
    depends_on:
      - db
    links:
      - db

$ cat scripts/install-extensions.sql 
CREATE EXTENSION hstore;

Мне пришлось изменить:

$ vim i5k/settings_prod.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': '5432',
        }
}

Затем я запустил docker-compose up --build

web_1  | Performing system checks...
web_1  | 
web_1  | System check identified no issues (0 silenced).
web_1  | Unhandled exception in thread started by <function wrapper at 0x7f8a9733a6d0>
web_1  | Traceback (most recent call last):
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/utils/autoreload.py", line 229, in wrapper
web_1  |     fn(*args, **kwargs)
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 116, in inner_run
web_1  |     self.check_migrations()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 168, in check_migrations
web_1  |     executor = MigrationExecutor(connections[DEFAULT_DB_ALIAS])
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/migrations/executor.py", line 19, in __init__
web_1  |     self.loader = MigrationLoader(self.connection)
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 47, in __init__
web_1  |     self.build_graph()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/migrations/loader.py", line 191, in build_graph
web_1  |     self.applied_migrations = recorder.applied_migrations()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/migrations/recorder.py", line 59, in applied_migrations
web_1  |     self.ensure_schema()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/migrations/recorder.py", line 49, in ensure_schema
web_1  |     if self.Migration._meta.db_table in self.connection.introspection.table_names(self.connection.cursor()):
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 162, in cursor
web_1  |     cursor = self.make_debug_cursor(self._cursor())
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 135, in _cursor
web_1  |     self.ensure_connection()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 130, in ensure_connection
web_1  |     self.connect()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/utils.py", line 98, in __exit__
web_1  |     six.reraise(dj_exc_type, dj_exc_value, traceback)
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 130, in ensure_connection
web_1  |     self.connect()
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/base/base.py", line 119, in connect
web_1  |     self.connection = self.get_new_connection(conn_params)
web_1  |   File "/usr/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 176, in get_new_connection
web_1  |     connection = Database.connect(**conn_params)
web_1  |   File "/usr/local/lib/python2.7/site-packages/psycopg2/__init__.py", line 127, in connect
web_1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
web_1  | django.db.utils.OperationalError: could not connect to server: Connection refused
web_1  |    Is the server running on host "localhost" (127.0.0.1) and accepting
web_1  |    TCP/IP connections on port 5432?
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 5432?

Что я упустил?

под db в docker-compose.yml добавьте строку:

db:
  .
  .
  .
  ports:
    - "5482:5432"    #это пример портов

потом в вашем settings_prod.py убедитесь, что переменная DATABASES включает правильный порт

import myproj.settings
myproj.settings.DATABASES = {. . ., 'PORT' : '5482', . . .}

ваш settings_prod.py также должен включать следующее:

и наконец, вам следует импортировать settings_prod.py из каждого Jupyter Notebook, который вы используете

Ответ или решение

Возникшая ошибка django.db.utils.OperationalError: could not connect to server: Connection refused в вашем проекте Django, работающем внутри Docker-контейнера, может быть вызвана несколькими факторами, связанными с настройкой сети между контейнерами и конфигурацией приложения. Рассмотрим основные шаги по ее устранению.

Проблемы и решения

1. Проверьте сетевые настройки Docker:

А) Порт на хосте и контейнере:

  • Убедитесь, что порт базы данных PostgreSQL внутри контейнера db корректно перенаправлен на хост-машину. В вашем файле docker-compose.yml добавьте:
db:
  ...
  ports:
    - "5432:5432"

Б) Использование правильного имени хоста:

  • Убедитесь, что в файле settings_prod.py параметр HOST имеет значение db, которое соответствует имени сервиса в docker-compose.yml:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'postgres',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'db',
        'PORT': '5432',
    }
}

2. Обеспечить зависимость контейнеров:

  • Ознакомьтесь с директивой depends_on, чтобы убедиться, что сервис web стартует только после успешного запуска сервиса db. Тем не менее, имейте в виду, что это не гарантирует готовность сервиса. Возможно, вам понадобится добавить логику ожидания (wait-for-it.sh или аналогичные).

3. Обновите зависимости:

  • Убедитесь, что версия psycopg2 соответствует установленной версии PostgreSQL для обеспечения совместимости. В вашем случае это:
psycopg2==2.8.6

4. Актуализация версий:

  • Рассмотрите возможность использования более современных версий Python и Django. Python 2 устарел и его поддержка закончилась в январе 2020 года, что может вызвать проблемы с совместимостью.

Дополнительные рекомендации

  • Логи и диагностика:

    • Проверьте логи сервера PostgreSQL на наличие ошибок или предупреждений, которые помогут понять причину отказа в соединении.
  • Безопасность:

    • В производственной среде замените стандартные параметры подключения к базе данных (USER, PASSWORD) на более безопасные значения.
  • Тестирование:

    • Попробуйте развернуть отдельный экземпляр PostgreSQL на хосте без Docker и подключиться к нему из Docker-контейнера web для изоляции проблемы.

Таким образом, шаги по решению этой проблемы помогут вам настроить связь между вашими контейнерами и обеспечить корректную работу приложения Django внутри Docker-среды. Исправление ошибок должно учитывать как технические аспекты, так и принципы безопасности и модернизации программного обеспечения.

Оцените материал
Добавить комментарий

Капча загружается...