Как создать подключение к postgres из докер контейнера?

Рейтинг: 0Ответов: 1Опубликовано: 16.02.2023

Всем привет! У меня есть телеграм бот, которого я решил перенести в докер контейнер. Бот подключается к postgres бд. Контейнер и postgres запущены на одном сервере. При запуске контейнера получаю ошибку

psycopg2.OperationalError: connection to server at "127.0.0.1", port 5432 failed: Connection refused Is the server running on that host and accepting TCP/IP connections?

имя бд: happy_bot имя пользователя (postgres): happy_bot

Вот pg_hba.conf :

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     trust
local   income_bot      income_bot                              password
local   happy_bot       happy_bot                               password
# IPv4 local connections:
# host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local   replication     all                                     peer
host    replication     all             127.0.0.1/32            scram-sha-256
host    replication     all             ::1/128                 scram-sha-256

сама строка подключения:

connection = pg.connect(database='happy_bot', user='happy_bot', password='happy_bot_password', host='127.0.0.1', port=5432)

Я пробовал писать в строке соединения host '127.0.0.1', 'localhost', ip сервера на котором запущена бд и контейнер

При запуске контейнера я пробовал добавлять --network='host', --add-host host.docker.internal:host-gateway

Я пробовал отключать фаервол ufw - не помогло

В голове уже каша, разные советы перепробовал, пока без результата. Помогите плиз

Ответы

▲ 3

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

Есть несколько способов достучаться до базы данных.

  1. Запустить докер в с хостовой сетью: docker run --network host .... В этом случае сетевые интерфейсы хоста, включая 127.0.0.1, будут видны внутри контейнера.

  2. Создать для вашего контейнера выделенную подсеть.

$ docker network create bot
03d99fd377bafbbaccea1625edb3c78522528bf585f434bffaed453fe882e463
$ ifconfig 
br-03d99fd377ba: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.20.0.1  netmask 255.255.0.0  broadcast 172.20.255.255
        ether 02:42:11:3f:40:b3  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

докер создасть сеть с именем br-<hex-digits> в котором шестнадцатиричные цифры равны первым 12 символам хэш-идентификатора сети.

В моём случае была создана сеть с префиксом 172.20.0.0/16. В этой сети у хоста адрес 172.20.0.1, а внутри контейнера адрес 172.20.0.2. Контейнер запускать командой docker run --network bot ....

Запустите постгрес, чтобы он слушал порт 5432 на адресе 172.20.0.1, и используйте этот адрес внутри вашего контейнера для связи с постгресом.

  1. Правильный вариант - воспользоваться docker compose.

Создайте docker-compose.yaml с двумя сервисами. Один сервис будет контейнер с вашим ботом, второй будет postgres.

Вариантов настройки docker-compose практически бесконечное множество. Вот пример:

version: '3.8'
services:
  db:
    hostname: postgres
    image: postgres:latest
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    ports:
      - '5432:5432'
    volumes: 
      - ./db/data:/var/lib/postgresql/data
      - ./db/init.sql:/docker-entrypoint-initdb.d/create_tables.sql
  bot:
    # здесь параметры вашего контейнера

Здесь важны две штуки. Во-первых, в сервисе db указано имя узла (hostname) postgres. Именно по этому имени будет виден сервер базы данных в контейнере bot. Докер возьмёт на себя DNS-распознавание имени и подстановку нужного адреса.

Во-вторых, базы данных будут лежать в файловой системе хоста. Это делается в секции volumes: локальный путь ./db/data мапится на путь /var/lib/postgresql/data внутри контейнера. При первом запуске контейнера база будет инциализирована скриптом ./db/init.sql

Как-то так.