не удалось перевести имя хоста “db” в адрес: Unknown host

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

Я пытаюсь следовать руководству, представленному по адресу: 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.

Решения

  1. Убедитесь, что команда выполняется в контейнере: Вместо выполнения makemigrations из терминала вашего хоста, запустите команду в контексте контейнера web:

    docker-compose run web python manage.py makemigrations

    Это позволит применить настройки, прописанные в settings.py, в том числе использование адреса db для базы данных.

  2. Добавление переменной окружения: Чтобы обеспечить большую гибкость при работе с окружениями, удобно использовать переменные окружения. Например, вы можете добавить следующую строку в 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'),
       }
    }
  3. Использование host.docker.internal: Если ваши проблемы с подключением не исчезают, возможно, стоит использовать host.docker.internal в качестве имени хоста. Это имя позволяет контейнерам Docker обращаться к хост-операционной системе. Вы можете изменить HOST в settings.py:

    'HOST': 'host.docker.internal',

    Эта опция может быть особенно полезна, если вы хотите, чтобы приложение в Docker имело доступ к службе, работающей на машине хоста.

Заключение

Ваша ошибка может быть легко устранена с учетом организации команд и среды, в которой они запускаются. Убедитесь, что ваши команды выполняются в правильном окружении Docker, используйте переменные окружения для гибкого управления конфигурацией, и, если необходимо, попробуйте host.docker.internal для обращения к хост-структуре. Эти подходы обеспечат стабильную работу вашего Django-приложения с базой данных PostgreSQL через Docker.

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

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