Как создать подключение к postgres из докер контейнера?
Всем привет! У меня есть телеграм бот, которого я решил перенести в докер контейнер. Бот подключается к 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 - не помогло
В голове уже каша, разные советы перепробовал, пока без результата. Помогите плиз
Ответы (1 шт):
Контейнер можно рассматривать как отдельный компьютер, работающий внутри вашей машины. У него своя локальная сеть, и он ничего не видит из того, что есть в вашем хосте.
Есть несколько способов достучаться до базы данных.
Запустить докер в с хостовой сетью:
docker run --network host .... В этом случае сетевые интерфейсы хоста, включая 127.0.0.1, будут видны внутри контейнера.Создать для вашего контейнера выделенную подсеть.
$ 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, и используйте этот адрес внутри вашего контейнера для связи с постгресом.
- Правильный вариант - воспользоваться
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
Как-то так.