Вопрос или проблема
Я пытаюсь следовать руководству, представленному по адресу: https://docs.docker.com/compose/django/
Когда я пытаюсь выполнить makemigrations, мне выдает ошибку Неизвестный хост, указанную в заголовке. Я пытаюсь использовать PostgreSQL с Django и Wagtail в качестве CMS
Мой docker-compose.yml выглядит следующим образом:
version: "3.9"
services:
db:
image: postgres
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
А мои настройки в файле settings.py выглядят следующим образом:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'postgres',
'USER': 'postgres',
'PASSWORD': 'postgres',
'HOST': 'db',
'PORT': 5432,
}
}
Я что-то пропустил?
Ваш код может запускаться в двух разных средах, и жесткая привязка информации о подключении может быть некорректной.
Вы упоминаете в комментарии, что запускаете что-то вроде:
docker-compose up -d db
python manage.py makemigrations
В этой среде python
работает вне Docker. Если вы добавите ports: [5432:5432]
в конфигурацию базы данных в файле docker-compose.yml
, база данных будет доступна, вероятно, через localhost
. С другой стороны, когда вы запускаете docker-compose up
, приложение работает внутри Docker, и база данных будет доступна по адресу db
.
Вы можете использовать переменную окружения для настройки этого. Мне полезно задавать этим переменным значения по умолчанию, которые были бы полезны для разработчика, и устанавливать их на разные значения в моей настройке развертывания (файл docker-compose.yml
).
DATABASES = {
'default': {
...
'HOST': os.getenv('DB_HOST', 'localhost'),
...
}
}
version: "3.9"
services:
db:
ports:
- '5432:5432' # делает это доступным из вашей среды разработки
...
web:
environment:
- DB_HOST=db
...
В моей ситуации оба db
и localhost
не сработали. Поэтому я установил settings.py
на:
DATABASES = {
"default": {
...
'HOST': 'host.docker.internal',
...
}
}
Что позволяет одному контейнеру Docker получать доступ ко всем другим контейнерам, подобно localhost. Источник идеи: https://stackoverflow.com/a/62147846/7924573
Ответ или решение
Ошибка "could not translate host name to ‘db’ to address: Unknown host" часто возникает в контексте использования Docker для настройки приложений, таких как Django с PostgreSQL. Давайте рассмотрим возможные причины и решения этого вопроса.
Проблема
Ошибка связана с тем, что Docker пытается установить соединение с базой данных PostgreSQL, используя имя хоста db
, указанное в файле settings.py
. Это имя соответствует сервису PostgreSQL, определенному в вашем файле docker-compose.yml
. Если вы получаете такое сообщение об ошибке, это может быть связано с тем, что ваш код выполняется вне контейнера Docker.
Контекст использования Docker
Когда вы запускаете команду
docker-compose up -d db
python manage.py makemigrations
вы создаете и запускаете только контейнер базы данных постгреса, но команда makemigrations
выполняется в окружении хоста, а не в контейнере web
. Таким образом, если вы указываете HOST: db
, это не может быть разрешено, так как это имя контейнера приложению, выполняющемуся вне Docker.
Решения
-
Убедитесь, что команда выполняется в контейнере: Вместо выполнения
makemigrations
из терминала вашего хоста, запустите команду в контексте контейнераweb
:docker-compose run web python manage.py makemigrations
Это позволит применить настройки, прописанные в
settings.py
, в том числе использование адресаdb
для базы данных. -
Добавление переменной окружения: Чтобы обеспечить большую гибкость при работе с окружениями, удобно использовать переменные окружения. Например, вы можете добавить следующую строку в
docker-compose.yml
, чтобы передать параметрDB_HOST
в контейнерweb
:version: "3.9" services: db: image: postgres environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres ports: - '5432:5432' # делает базу данных доступной из вашего окружения разработки web: build: . command: python manage.py runserver 0.0.0.0:8000 volumes: - .:/code ports: - "8000:8000" depends_on: - db environment: - DB_HOST=db
Затем в
settings.py
вы можете использовать переменные окружения для установки хоста:import os DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('POSTGRES_DB', 'postgres'), 'USER': os.getenv('POSTGRES_USER', 'postgres'), 'PASSWORD': os.getenv('POSTGRES_PASSWORD', 'postgres'), 'HOST': os.getenv('DB_HOST', 'localhost'), # localhost для разработки вне Docker 'PORT': os.getenv('DB_PORT', '5432'), } }
-
Использование
host.docker.internal
: Если ваши проблемы с подключением не исчезают, возможно, стоит использоватьhost.docker.internal
в качестве имени хоста. Это имя позволяет контейнерам Docker обращаться к хост-операционной системе. Вы можете изменитьHOST
вsettings.py
:'HOST': 'host.docker.internal',
Эта опция может быть особенно полезна, если вы хотите, чтобы приложение в Docker имело доступ к службе, работающей на машине хоста.
Заключение
Ваша ошибка может быть легко устранена с учетом организации команд и среды, в которой они запускаются. Убедитесь, что ваши команды выполняются в правильном окружении Docker, используйте переменные окружения для гибкого управления конфигурацией, и, если необходимо, попробуйте host.docker.internal
для обращения к хост-структуре. Эти подходы обеспечат стабильную работу вашего Django-приложения с базой данных PostgreSQL через Docker.