Подтвердить что ты не робот

Разрешить контейнер docker подключаться к локальной базе данных postgres

Недавно я играл с Docker и QGIS и установил контейнер, следуя инструкциям в этом руководстве.

Все отлично работает, хотя я не могу подключиться к локальной базе данных postgres, которая содержит все мои ГИС-данные. Я полагаю, это потому, что моя база данных postgres не настроена на прием удаленных подключений и редактирует файлы conf postgres для разрешения удаленных подключений, используя инструкции из этой статьи.

Я все еще получаю сообщение об ошибке, когда пытаюсь подключиться к своей базе данных, на которой запущен QGIS в Docker: не удалось подключиться к серверу: Connection refused Is the server running on host "localhost" (::1) and accepting TCP/IP connections to port 5433? Сервер postgres работает, и я отредактировал мой файл pg_hba.conf, чтобы разрешить подключения с диапазона IP-адресов (172.17.0.0/32). Ранее я запрашивал IP-адрес контейнера Docker с помощью docker ps и, хотя IP-адрес изменяется, он до сих пор всегда находился в диапазоне 172.17.0.x

Есть идеи, почему я не могу подключиться к этой базе данных? Наверное, что-то очень простое я представляю!

Я использую Ubuntu 14.04; Postgres 9,3

4b9b3361

Ответ 1

TL; DR

  • Используйте 172.17.0.0/16 как диапазон IP-адресов, а не 172.17.0.0/32.
  • Не используйте localhost для подключения к базе данных PostgreSQL на вашем хосте, но вместо этого вместо IP-адреса хоста. Чтобы контейнер переносился, запустите контейнер с флагом --add-host=database:<host-ip> и используйте database как имя хоста для подключения к PostgreSQL.
  • Убедитесь, что PostreSQL настроен на прослушивание соединений на всех IP-адресах, а не только на localhost. Найдите настройку listen_addresses в файле конфигурации PostgreSQL, обычно находящемся в /etc/postgresql/9.3/main/postgresql.conf (кредиты @DazmoNorton).

Длинная версия

172.17.0.0/32 не является диапазоном IP-адресов, а единственным адресом (namly 172.17.0.0). Контейнер Docker никогда не получит этот адрес, потому что это сетевой адрес интерфейса Docker bridge (docker0).

Когда Docker запустится, он создаст новый сетевой интерфейс моста, который вы можете легко увидеть при вызове ip a:

$ ip a
...
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN 
    link/ether 56:84:7a:fe:97:99 brd ff:ff:ff:ff:ff:ff
    inet 172.17.42.1/16 scope global docker0
       valid_lft forever preferred_lft forever

Как вы можете видеть, в моем случае интерфейс docker0 имеет IP-адрес 172.17.42.1 с сетевой маской /16 (или 255.255.0.0). Это означает, что сетевой адрес 172.17.0.0/16.

IP-адрес назначается случайным образом, но без какой-либо дополнительной конфигурации он всегда будет находиться в сети 172.17.0.0/16. Для каждого контейнера Docker будет назначен случайный адрес из этого диапазона.

Это означает, что если вы хотите предоставить доступ из всех возможных контейнеров в свою базу данных, используйте 172.17.0.0/16.

Ответ 2

Решение Docker для Mac

17.06 года

Благодаря комментарию @Birchlabs, теперь это специальное DNS-имя доступно только для Mac:

docker run -e DB_PORT=5432 -e DB_HOST=docker.for.mac.host.internal

Начиная с 17.12.0-cd-mac46, docker.for.mac.host.internal следует использовать docker.for.mac.localhost. См. Примечание к выпуску для деталей.

Старая версия

Ответ @helmbert хорошо объясняет проблему. Но Docker для Mac не предоставляет мостовую сеть, поэтому мне пришлось сделать этот трюк, чтобы обойти ограничение:

$ sudo ifconfig lo0 alias 10.200.10.1/24

Откройте /usr/local/var/postgres/pg_hba.conf и добавьте эту строку:

host    all             all             10.200.10.1/24            trust

Откройте /usr/local/var/postgres/postgresql.conf и отредактируйте изменения listen_addresses:

listen_addresses = '*'

Перезагрузите сервис и запустите свой контейнер:

$ PGDATA=/usr/local/var/postgres pg_ctl reload
$ docker run -e DB_PORT=5432 -e DB_HOST=10.200.10.1 my_app 

То, что делает этот обходной путь, в основном совпадает с ответом @helmbert, но использует IP-адрес, который присоединен к lo0 вместо сетевого интерфейса docker0.

Ответ 3

Простое решение для Mac:

Новейшая версия Docker (18.03) предлагает встроенное решение для переадресации портов. Внутри вашего docker-контейнера просто установите для хоста db значение host.docker.internal. Это будет перенаправлено на хост, на котором работает контейнер докеров.

Документация для этого здесь: https://docs.docker.com/docker-for-mac/networking/#per-container-ip-addressing-is-not-possible

Ответ 4

Простое решение

Просто добавьте --network=host для docker run. Все это!

Таким образом, контейнер будет использовать сеть хоста, поэтому localhost и 127.0.0.1 будут указывать на хост (по умолчанию они указывают на контейнер). Пример:

docker run -d --network=host \
  -e "DB_DBNAME=your_db" \
  -e "DB_PORT=5432" \
  -e "DB_USER=your_db_user" \
  -e "DB_PASS=your_db_password" \
  -e "DB_HOST=127.0.0.1" \
  --name foobar foo/bar

Ответ 5

В Ubuntu:

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

sudo iptables -L -n

Образец ВЫХОДА:

Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.2           tcp dpt:3306
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            172.17.0.3           tcp dpt:22

Здесь 3306 используется как порт базы данных Docker на 172.17.0.2 IP, если этот порт недоступен, выполните следующую команду -

sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT

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

  host: 172.17.0.2 
  adapter: mysql
  database: DATABASE_NAME
  port: 3307
  username: DATABASE_USER
  password: DATABASE_PASSWORD
  encoding: utf8

В CentOS:

Сначала вы должны проверить, доступен ли порт базы данных Docker в вашем брандмауэре, выполнив следующую команду -

sudo firewall-cmd --list-all

Образец ВЫХОДА:

  target: default
  icmp-block-inversion: no
  interfaces: eno79841677
  sources: 
  services: dhcpv6-client ssh
  **ports: 3307/tcp**
  protocols: 
  masquerade: no
  forward-ports: 
  sourceports: 
  icmp-blocks: 
  rich rules:

Здесь 3307 используется в качестве порта базы данных Docker на 172.17.0.2 IP, если этот порт недоступен, выполните следующую команду -

sudo firewall-cmd --zone=public --add-port=3307/tcp

На сервере Вы можете добавить порт навсегда

sudo firewall-cmd --permanent --add-port=3307/tcp
sudo firewall-cmd --reload

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

Ответ 6

для docker-compose вы можете попробовать просто добавить

network_mode: "host"

пример:

version: '2'
services:
  feedx:
    build: web
    ports:
    - "127.0.0.1:8000:8000"
    network_mode: "host"

https://docs.docker.com/compose/compose-file/#network_mode

Ответ 7

Еще одна вещь, необходимая для моей установки, заключалась в том, чтобы добавить

172.17.0.1  localhost

to /etc/hosts

чтобы Docker указывал на 172.17.0.1 как имя узла БД и не полагался на изменение внешнего ip для поиска БД. Надеюсь, это поможет кому-то еще с этой проблемой!

Ответ 8

Чтобы настроить что-то простое, разрешающее соединение Postgresql из контейнера Docker с моим локальным хостом, я использовал это в postgresql.conf:

listen_addresses = '*'

И добавил этот pg_hba.conf:

host    all             all             172.17.0.0/16           password

Затем перезагрузите компьютер. Мой клиент из контейнера Docker (который был на 172.17.0.2) мог затем подключиться к Postgresql, работающему на моем локальном хосте, используя host: пароль, базу данных, имя пользователя и пароль.

Ответ 9

Другим решением является уровень обслуживания. Вы можете определить том службы и установить каталог данных PostgreSQL Host в том томе. Подробнее см. Данный файл компоновки.

version: '2'
services:
  db:   
    image: postgres:9.6.1
    volumes:
      - "/var/lib/postgresql/data:/var/lib/postgresql/data" 
    ports:
      - "5432:5432"

Таким образом, другая служба PostgreSQL будет работать под контейнером, но использует тот же каталог данных, который использует служба PostgreSQL.