Не удалось преобразовать имя хоста "db" в адрес с помощью Postgres, Docker Compose и Psycopg2

В одной папке у меня 3 файла: base.py, Dockerfile и docker-compose.yml.

base.py:

import psycopg2

conn = psycopg2.connect("dbname='base123' user='postgres' host='db' password='pw1234'")

Dockerfile:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -y install python-pip
RUN apt-get update
RUN pip install --upgrade pip
RUN pip install psycopg2-binary

COPY base.py base.py

RUN python base.py

docker-compose.yml:

version: '3'
services:
  db:
    image: 'postgres:latest'
    expose:
      - "5432"
    environment:
      POSTGRES_PASSWORD: pw1234
      POSTGRES_DB: base123
  aprrka:
    build: .    
    depends_on:
      - db

После запуска docker-compose up я получил следующую ошибку:

Traceback (most recent call last):
  File "base.py", line 5, in <module>
conn = psycopg2.connect("dbname='base123' user='postgres' host='db' password='pw1234'")
   File "/usr/local/lib/python2.7/dist-packages/psycopg2/__init__.py", line 130, in connect
    conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: could not translate host name "db" to address: Name or service not known

ERROR: Service 'aprrka' failed to build: The command '/bin/sh -c python base.py' returned a non-zero code: 1

Я не знаю, почему у меня такая ошибка. Я открыл порт 5432. По умолчанию Compose настраивает единую сеть для приложения. Каждая служба подключается к сети по умолчанию, я думаю, что мое приложение с postgres должно работать вместе. Я написал неверный docker-compose.yml?

Ответ Джека Гора отвечает на ваш вопрос. Один из подходов к диагностике мог заключаться в использовании известного исправного второго контейнера для доступа к db. См. Документацию к образу на docs.docker.com и использование образа adminer (docs.docker.com/samples/library/postgres/…). Во-вторых, Dockerfile выиграет от уменьшения количества создаваемых слоев за счет уменьшения количества команд RUN. Например RUN apt-get update && apt-get -y install python-pip (финальный apt-get update вам не нужен).

DazWilkin 08.08.2018 18:46
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
37
1
72 288
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Проблема в том, что вы не должны запускать python base.py как часть директивы RUN.

Директива RUN выполняется только при построении образа. Контейнер postgres на данный момент не запущен, и сеть не создана. Вместо этого вы хотите использовать директиву CMD.

Измените Dockerfile на это:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get -y install python-pip
RUN apt-get update
RUN pip install --upgrade pip
RUN pip install psycopg2-binary

COPY base.py base.py

CMD ["python", "base.py"]

Вышеупомянутое должно привести к разрешению имени хоста db. Однако, если в вашем коде Python нет логики повторного подключения для подключения к базе данных, контейнер, скорее всего, все равно выйдет из строя. Это связано с тем, что контейнер postgres будет работать, но база данных не будет готова принимать соединения.

Это можно временно исправить, добавив restart: always к вашему docker-compose.yml.

version: '3'
services:
  db:
    image: 'postgres:latest'
    expose:
      - "5432"
    environment:
      POSTGRES_PASSWORD: pw1234
      POSTGRES_DB: base123
  aprrka:
    restart: always
    build: .    
    depends_on:
      - db

Надеюсь, это поможет вам начать работу.

Спасибо! Как это ни печально, но я до сих пор не знаю, как исправить следующую ошибку. aprrka_1 | Отслеживание (последний вызов последним): файл «base.py», строка 5, в <module> conn = psycopg2.connect («dbname = 'base123' user = 'postgres' host = 'db' password = 'pw1234'» ) Файл "/usr/local/lib/python2.7/dist-packages/psycopg2/__init__.py‌", строка 130, в connect conn = _connect (dsn, connection_factory = connection_factory, ** kwasync) psycopg2.OperationalError: может не подключается к серверу: в соединении отказано. Сервер работает на хосте «db» (172.20.0.2) и принимает соединения TCP / IP на порту 5432?

gongarek 08.08.2018 20:06

Эту ошибку пыталась исправить вторая часть моего ответа. Вам нужно либо добавить логику переподключения в свой код, либо добавить restart: always в свой файл compose. Вы пробовали это?

Jack Gore 08.08.2018 20:10

Да. Это работает, но первые попытки подключения к базе данных не увенчались успехом. Нужно ли мне вводить в моем файле base.py некоторое «время ожидания», чтобы правильно установить соединение без ошибок? Я полагаю, что это не будет «лучше» для всего моего образа Docker, но будет лучше посмотреть, как он работает. Мое решение правильное?

gongarek 08.08.2018 20:17

Да, это отдельный вопрос, но вы хотите реализовать в своем коде какой-то механизм ожидания.

Jack Gore 08.08.2018 20:19

если вы добавите это в свой контейнер db в свой docker-compose.yml, это должно решить проблему

environment:
  - "POSTGRES_HOST_AUTH_METHOD=trust"

Это также сделает вашу базу данных небезопасной.

Ryan Mckenna 18.10.2020 20:47

Добавьте базу данных и веб-сервис на та же сеть в файл docker compose. Также служба базы данных ссылка на сайт и запуск веб-службы после запуска службы базы данных.

После правильного добавления конфигурации сеть, ссылка и зависит_он в файл docker compose проблема будет исправлена.

Пример конфигурации:

  services:
      db:
          container_name: db
          networks:
              - djangonetwork
      web:
          depends_on:
             - db
          links:
             - db:db
          networks:
             - djangonetwork

  networks:
      djangonetwork:
          driver: bridge

В моем файле создания докеров я использовал имя сети как «djangonetwork», вы можете использовать любое другое имя.

Приведенная выше конфигурация помогла мне решить проблему «Не удалось перевести имя хоста db».

Ну стреляйте. Это просто прошло для меня. Спасибо.

waterloomatt 18.02.2021 05:00

Другой возможный сценарий,

Проверьте, использовались ли порты другим докер-контейнером. Используйте команду:

$ docker container ls --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}" -a

Затем измените свои порты / выставьте в файле docker-compose

Если вы используете docker-compose, сначала добавьте эту строку в свой .yml:

environment:
  - "POSTGRES_HOST_AUTH_METHOD=trust"

После этого вы запускаете только докер db:

docker-compose up db

Обычно он должен начинаться с такого сообщения:

Recreating db... done
Attaching to db
db_1           | ********************************************************************************
db_1           | WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow
db_1           |          anyone with access to the Postgres port to access your database without
db_1           |          a password, even if POSTGRES_PASSWORD is set. See PostgreSQL
db_1           |          documentation about "trust":
db_1           |          https://www.postgresql.org/docs/current/auth-trust.html
db_1           |          In Docker's default configuration, this is effectively any other
db_1           |          container on the same system.
db_1           | 
db_1           |          It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace
db_1           |          it with "-e POSTGRES_PASSWORD=password" instead to set a password in
db_1           |          "docker run".
db_1           | ********************************************************************************

Другие вопросы по теме