dockerコンテナーがローカル/ホストの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)。私は以前にを使用してDockerコンテナーのIPアドレスを問い合わせましたdocker psが、IPアドレスは変更されましたが、これまでのところ常に172.17.0.xの範囲にありました

このデータベースに接続できない理由はありますか?たぶん私が想像する非常にシンプルなもの!

私はUbuntu 14.04を実行しています。Postgres 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アドレスで接続をリッスンするように設定されていることを確認してくださいlocalhostlisten_addresses通常は/etc/postgresql/9.3/main/postgresql.conf(@DazmoNortonへのクレジット)にあるPostgreSQLの構成ファイルで設定を探します。

ロングバージョン

172.17.0.0/32IPアドレスの範囲ではなく、単一のアドレス(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ネットマスクを持つIPアドレスがあります。これは、ネットワークアドレスがであることを意味します。/16255.255.0.0172.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接続情報を変更する必要がありますか?たとえば、Dockerコンテナー内から接続している場合、ホストはまだ「localhost」ですか?
marty_c 2015

ああ、それは重要なポイントです。いいえ、localhostDockerコンテナー内のホストシステムではありません。ホストシステムのパブリックIPアドレスに接続してみます。コンテナをポータブルに保つには、コンテナをで起動し、ホスト名として--add-host=database:<host-ip>使用しdatabaseて、Dockerコンテナ内からPostgreSQLホストに接続することもできます。
helmbert 2015

6
もう一枚必要でした。また/etc/postgresql/9.3/main/postgresql.conf、サーバーのeth0IPアドレスを編集してに追加する必要がありましたlisten_addresses。デフォルトでlisten_addressesは、postgres localhostのみがバインドされます。
Dzamo Norton、2015

@DzamoNorton、ヒントをありがとう!私はそれに応じて私の答えを更新しました。
helmbert 2015年

@helmbert host-ipは仮想マシンまたはDockerコンテナーのIPアドレスですか?
Mr.D 2017

56

Docker for 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の答えは問題をよく説明しています。しかし、Docker for 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の回答と同じですがlo0docker0ネットワークインターフェイスの代わりに接続されているIPアドレスを使用します。


3
これは2017年4月4日現在でも最新ですか?
Petrus Theron 2017

私はデータベースを公開しないこの方法が好きです。ところで、CentOSでこれを使用できますか?指定したエイリアスコマンドを使用しようとすると、「エイリアス:不明なホスト」というエラーメッセージが表示されました。
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 2017

5
18.03 host.docker.internal以降に変更されたようですが、他のオプションは引き続き使用できますが、非推奨です(Source)。
gseva

44

Mac向けのシンプルなソリューション:

最新バージョンのdocker(18.03)は、組み込みのポート転送ソリューションを提供します。Dockerコンテナー内では、dbホストをに設定するだけhost.docker.internalです。これは、Dockerコンテナーが実行されているホストに転送されます。

このドキュメントはこちらです:https : //docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from-a-container-to-a-service-on-the-host


3
これは今のところ断然最高の答えです!ずっと簡単で、どうあるべきか。
bjm88 2018

2
されるhost.docker.internalだけのMacに限ら?
Dragas 2018年

@Dragasのドキュメントによれば、「Mac以外では機能しません」が、同じDNS名がDocker for Windowsのドキュメントに記載されているため、「Docker for ...」に限定されていると思います。どちらにしても開発専用です。これを使用するDockerイメージを出荷することを意図していません。
ルバーブ

WindowsとMacでのみ動作します。私の場合、ubuntuが機能していません
Azri Zakaria

16

シンプルなソリューション

に追加--network=hostするだけdocker 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

Debianで動作します。postgresql.confとpg_hba.confの変更を試みましたが、これはより簡単で高速です。
frmbelz

2

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は、172.17.0.2 IPのDockerデータベースポートとして使用されます。このポートが使用できない場合は、次のコマンドを実行します-

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のDockerデータベースポートとして使用されます。このポートが使用できない場合は、次のコマンドを実行します-

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

サーバーでは、ポートを永続的に追加できます

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

これで、上記の構成により、ローカルシステムからDockerデータベースに簡単にアクセスできます。


私はこれが古いことを知っていますが、今、ローカルシステムから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"

dockerの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内でこれを使用し、私はlocalhostにドッカコンテナを:

listen_addresses = '*'

そして、このpg_hba.confを追加しました:

host    all             all             172.17.0.0/16           password

その後、再起動します。Dockerコンテナ(172.17.0.2にあります)からのクライアント、host:password、データベース、ユーザー名、およびパスワードを使用して、ローカルホストで実行されているPostgresqlに接続できます。


0

私のセットアップに必要なもう1つは、

172.17.0.1  localhost

/etc/hosts

Dockerが172.17.0.1DBホスト名としてポイントし、DBを見つけるために変更する外部IPに依存しないようにするためです。これがこの問題で他の誰かを助けることを願っています!


14
これは悪い解決策です。通常、Localhostは127.0.0.1を指す必要があります。この特定のケースで機能しても、変更すると望ましくない結果が生じる可能性があります。
アレックス

2
より良い方法は、コンテナを実行するときにdatabaseホストをセットアップすることです--add-host=database:172.17.0.1。次に、アプリにそのホストを指定します。これにより、コンテナー内のIPアドレスをハードコーディングする必要がなくなります。
jaredsk 2017

1
これ--add-host=database:172.17.0.1が望ましい
Luis Martins

-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.