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

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

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

Я все еще получаю сообщение об ошибке при попытке подключиться к моей базе данных под управлением 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

6 ответов


TL; DR

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

текст

172.17.0.0/32 - это не ряд IP-адресов, но один адрес (namly 172.17.0.0). Ни один контейнер Docker никогда не получит этот адрес, потому что это сетевой адрес моста Docker (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.


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

17.06 и далее

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

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 хорошо объясняет проблему. Но Докер для 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 сетевой интерфейс.


простое решение для mac:

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

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


еще одна вещь, необходимая для моей установки, - это добавить

172.17.0.1  localhost

to /etc/hosts

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


В 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 --reload

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


другое решение-том службы, вы можете определить том службы и подключить каталог данных PostgreSQL хоста в этом томе. Проверьте данный файл compose для деталей.

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

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