도커 컨테이너가 로컬 / 호스트 postgres 데이터베이스에 연결하도록 허용


143

최근에 Docker 및 QGIS를 가지고 놀았 으며이 자습서 의 지침에 따라 컨테이너를 설치했습니다 .

모든 GIS 데이터가 포함 된 localhost postgres 데이터베이스에 연결할 수 없지만 모든 것이 잘 작동합니다. postgres 데이터베이스가 원격 연결을 허용하도록 구성되지 않았고이 기사 의 지시 사항을 사용하여 원격 연결을 허용하기 위해 postgres conf 파일을 편집하고 있기 때문 입니다.

Docker에서 QGIS를 실행하는 데이터베이스에 연결하려고 할 때 여전히 오류 메시지가 나타납니다. 서버에 연결할 수 없습니다 : 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 ps했지만 IP 주소가 변경되었지만 지금까지는 항상 172.17.0.x 범위였습니다.

이 데이터베이스에 연결할 수없는 이유가 있습니까? 아마 내가 생각하는 아주 간단한 것!

우분투 14.04를 실행 중입니다. 포스트그레스 9.3

답변:


149

TL; DR

  1. 172.17.0.0/16아닌 IP 주소 범위로 사용하십시오 172.17.0.0/32.
  2. localhost호스트의 PostgreSQL 데이터베이스에 연결하는 데 사용하지 말고 대신 호스트의 IP를 사용하십시오. 컨테이너를 이식 가능하게 유지하려면 --add-host=database:<host-ip>플래그로 컨테이너를 시작하고 databasePostgreSQL에 연결하기위한 호스트 이름으로 사용하십시오 .
  3. PostreSQL이뿐만 아니라 모든 IP 주소의 연결을 수신하도록 구성되어 있는지 확인하십시오 localhost. listen_addresses일반적으로 /etc/postgresql/9.3/main/postgresql.conf(@DazmoNorton의 신용에있는) PostgreSQL 구성 파일에서 설정 을 찾으십시오 .

긴 버전

172.17.0.0/32없는 범위의 IP 주소,하지만 하나의 주소는 (namly 172.17.0.0). Docker 브리지 ( docker0) 인터페이스 의 네트워크 주소이므로 Docker 컨테이너에는 해당 주소가 할당되지 않습니다 .

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인터페이스 172.17.42.1에 넷 마스크가 /16(또는 255.255.0.0) 인 IP 주소 가 있습니다. 이는 네트워크 주소가 172.17.0.0/16입니다.

IP 주소는 임의로 할당되지만 추가 구성이 없으면 항상 172.17.0.0/16네트워크에있게됩니다. 각 Docker 컨테이너에 대해 해당 범위의 임의 주소가 할당됩니다.

즉, 가능한 모든 컨테이너에서 데이터베이스로 액세스 권한을 부여하려면을 사용하십시오 172.17.0.0/16.


1
귀하의 의견에 감사드립니다. pg_hba.conf제안한 주소 로 내 주소를 변경 했지만 postgres 서비스를 중지했다가 다시 시작한 후에도 동일한 연결 오류 메시지가 나타납니다. 내 ipv4 연결에 줄을 추가했습니다. 다른 곳에서 제안하는 주소를 추가해야합니까? 또는 Docker에서 실행되는 QGIS 앱에서 postgres 연결 정보를 변경해야합니까? 예를 들어, 도커 컨테이너 내에서 연결하는 경우 호스트가 여전히 'localhost'입니까?
marty_c

아, 그것은 중요한 포인트입니다. 아니요, localhostDocker 컨테이너 내부의 호스트 시스템이 아닙니다. 호스트 시스템의 퍼블릭 IP 주소에 연결하십시오. 컨테이너를 이식 가능하게 유지하기 위해 컨테이너를 시작 하고 Docker 컨테이너 내에서 PostgreSQL 호스트에 연결하기 위해 --add-host=database:<host-ip>간단히 database호스트 이름으로 사용할 수 있습니다.
helmbert

6
한 조각 더 필요했습니다. 또한 /etc/postgresql/9.3/main/postgresql.conf서버의 eth0IP 주소를 편집 하고에 추가 해야했습니다 listen_addresses. 기본적으로 listen_addressespostgres는 바인드 localhost에만 바인딩 됩니다.
Dzamo Norton

@DzamoNorton, 힌트 주셔서 감사합니다! 이에 따라 답변을 업데이트했습니다.
helmbert

@helmbert host-ip는 가상 머신 또는 도커 컨테이너의 IP 주소입니까?
Mr.D

56

Mac 용 Docker 솔루션

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 용 Docker 는 브리지 네트워크를 노출시키지 않으므로 제한을 해결하기 위해이 트릭을 수행해야했습니다.

$ 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의 답변과 동일하지만 네트워크 인터페이스 lo0대신 연결된 IP 주소를 사용합니다 docker0.


3
여전히 2017 년 4 월 4 일 현재입니까?
Petrus Theron

나는 데이터베이스를 노출시키지 않는이 방법을 좋아한다. BTW, CentOS에서 이것을 사용할 수 있습니까? 다음과 같은 오류가 발생했습니다. alias : 제공 한 alias 명령을 사용하려고 할 때 알 수없는 호스트입니다.
Tsung Goh

6
Docker 17.06.0-rc1-ce-mac13 (2017 년 6 월 1 일)부터 macOS에는 더 나은 방법이 있습니다. 컨테이너는 호스트를 인식합니다 docker.for.mac.localhost. 이것은 호스트 시스템의 IP입니다. 컨테이너의 호스트 데이터베이스에서 해당 항목을 조회합니다. docker run alpine /bin/sh -c 'getent hosts docker.for.mac.localhost'
Birchlabs

@Birchlabs 정말 대단합니다!
qqilihq

5
host.docker.internal18.03 이후로 변경된 것 같지만 다른 옵션은 계속 사용할 수 있지만 더 이상 사용되지 않습니다 ( Source ).
gseva

44

Mac 용 간단한 솔루션 :

최신 버전의 도커 (18.03)는 내장 포트 포워딩 솔루션을 제공합니다. 도커 컨테이너 안에는 db 호스트가로 설정되어 host.docker.internal있습니다. 이것은 도커 컨테이너가 실행되는 호스트로 전달됩니다.

이에 대한 설명서는 다음과 같습니다. https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host


3
이것은 지금까지 가장 좋은 대답입니다! 더 쉽고 어떻게 해야하는지.
bjm88

2
입니다 host.docker.internal만 맥 제한?
Dragas

문서에 따르면 @Dragas는 "Mac 외부에서는 작동하지 않습니다"이지만 Windows 용 Docker 문서에는 동일한 DNS 이름이 언급되어 있으므로 "Docker for ..."로 제한됩니다. 어느 쪽이든 개발 전용입니다.이를 사용하는 도커 이미지를 제공하지는 않습니다.
대황

Windows 및 Mac에서만 작동합니다. 제 경우에는 우분투가 작동하지 않습니다
Azri Zakaria

16

간단한 솔루션

그냥 추가 --network=hostdocker run . 그게 다야!

이 방법 컨테이너는 호스트의 네트워크를 사용되므로 localhost127.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

1
조심해! 내 생각에 맞는이 솔루션은 macOS에서 작동하지 않습니다. 왜 작동하지 않는지 알아 내려고 시간을 낭비하지 마십시오. 에서보세요 : github.com/docker/for-mac/issues/2716
jfcorugedo

데비안에서 작동합니다. postgresql.conf 및 pg_hba.conf 변경을 시도했지만 더 간단하고 빠릅니다.
frmbelz

2

우분투에서 :

먼저 다음 명령을 사용하여 시스템에서 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이 포트는 다음 명령을 사용할 수 실행하지 않은 경우, 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이 포트는 다음 명령을 사용할 수 실행하지 않은 경우, 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 데이터베이스에 쉽게 액세스 할 수 있습니다.


나는 이것이 오래 되었다는 것을 알고 있지만 이제는 다음 구성을 통해 로컬 시스템에서 Docker 데이터베이스에 쉽게 액세스 할 수 있습니다 . 그는 로컬 데이터베이스를 가지고 있으며 다른 방법으로 로컬 데이터베이스에 연결하려고하는 도커 앱을 가지고 있습니다.
Craicerjack

2

여기에 게시 된 솔루션이 효과가 없습니다. 따라서 비슷한 문제에 직면 한 사람을 돕기 위해이 답변을 게시하고 있습니다.

OS : Ubuntu 18
PostgreSQL : 9.5 (Ubuntu에서 호스팅)
Docker : 서버 응용 프로그램 (PostgreSQL에 연결)

docker-compose.yml을 사용하여 응용 프로그램을 작성하고 있습니다.

1 단계 : 추가하십시오host.docker.internal:<docker0 IP>

version: '3'
services:
  bank-server:
    ...
    depends_on:
      ....
    restart: on-failure
    ports:
      - 9090:9090
    extra_hosts:
      - "host.docker.internal:172.17.0.1"

도커의 IP를 찾으려면 i.e. 172.17.0.1 (in my case)다음을 사용할 수 있습니다.

$> ifconfig docker0
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255

또는

$> ip a
1: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

2 단계 : postgresql.conf에서 listen_addresses를listen_addresses = '*'

3 단계 : pg_hba.conf에서이 줄을 추가하십시오

host    all             all             0.0.0.0/0               md5

4 단계 : 이제 다음을 사용하여 postgresql 서비스를 다시 시작하십시오.sudo service postgresql restart

5 단계 :host.docker.internal 호스트 이름을 사용하여 서버 응용 프로그램에서 데이터베이스를 연결 하십시오 .
전의:jdbc:postgresql://host.docker.internal:5432/bankDB

즐겨!!



1

PostgreSQL의 연결을 허용 뭔가 간단한 설정하려면 에서 나는 postgresql.conf의이 사용 내 로컬 호스트에 고정 표시기 컨테이너를 :

listen_addresses = '*'

그리고이 pg_hba.conf를 추가했습니다 :

host    all             all             172.17.0.0/16           password

그런 다음 다시 시작하십시오. Docker 컨테이너 (172.17.0.2)의 클라이언트 host : password, database, username 및 password를 사용하여 로컬 호스트에서 실행되는 Postgresql에 연결할 수 있습니다.


0

설정에 필요한 또 다른 것은

172.17.0.1  localhost

/etc/hosts

Docker는 172.17.0.1DB 호스트 이름을 가리키고 DB를 찾기 위해 외부 IP 변경에 의존하지 않습니다. 이것이이 문제를 가진 다른 사람을 돕기를 바랍니다!


14
이것은 나쁜 해결책입니다. 로컬 호스트는 일반적으로 127.0.0.1을 가리켜 야합니다. 이 특별한 경우에는 변경하더라도 바람직하지 않은 결과가 발생할 수 있습니다.
Alex

2
더 좋은 방법은 컨테이너를 실행할 때 database호스트 를 설정하는 것 --add-host=database:172.17.0.1입니다. 그런 다음 앱을 해당 호스트를 가리 킵니다. 이렇게하면 컨테이너 내부의 IP 주소를 하드 코딩하지 않아도됩니다.
jaredsk

1
--add-host=database:172.17.0.1바람직
루이스 마틴

-3

다른 솔루션은 서비스 볼륨입니다. 서비스 볼륨을 정의하고 해당 볼륨에 호스트의 PostgreSQL 데이터 디렉토리를 마운트 할 수 있습니다. 세부 사항은 제공된 작성 파일을 확인하십시오.

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

이렇게하면 다른 PostgreSQL 서비스가 컨테이너에서 실행되지만 PostgreSQL 서비스를 호스트하는 동일한 데이터 디렉토리를 사용합니다.


1
이것은 아마도 실행중인 호스트 PostgreSQL 서비스와 쓰기 충돌을 일으킬 것입니다
Petrus Theron

이 경우 호스트 서비스를 중지하면 문제가 해결 될 것이라고 생각합니다.
Hrishi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.