Вопрос или проблема
Я нашел проект Django и не смог запустить его в контейнере Docker следующим образом:
git clone https://github.com/NAL-i5K/django-blast.git
$ 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
для изоляции проблемы.
- Попробуйте развернуть отдельный экземпляр PostgreSQL на хосте без Docker и подключиться к нему из Docker-контейнера
Таким образом, шаги по решению этой проблемы помогут вам настроить связь между вашими контейнерами и обеспечить корректную работу приложения Django внутри Docker-среды. Исправление ошибок должно учитывать как технические аспекты, так и принципы безопасности и модернизации программного обеспечения.