Разрешить контейнер 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 73

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 solution

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

до /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.