Dockerコンテナー内から、マシンのローカルホストに接続するにはどうすればよいですか?


1451

したがって、Dockerコンテナー内でNginxを実行しています。localhostでmysqlを実行しています。Nginx内からMySqlに接続します。MySqlはローカルホストで実行されており、ポートを外部に公開していないため、マシンのIPアドレスではなくローカルホストにバインドされています。

このDockerコンテナ内からローカルホスト上のこのMySqlまたは他のプログラムに接続する方法はありますか?

この質問は、DockerホストのIPアドレスがネットワーク内のパブリックIPまたはプライベートIPである可能性がある、または可能性があるため、「Dockerコンテナー内からdockerホストのIPアドレスを取得する方法」とは異なります。 Dockerコンテナー内から到達できません(AWSなどでホストされている場合は、パブリックIPを意味します)。DockerホストのIPアドレスを持っている場合でも、Dockerネットワークがオーバーレイ、ホスト、ブリッジ、macvlanなどの可能性があるため、そのIPアドレスがコンテナの到達可能性を制限するため、コンテナ内からdockerホストに接続できるわけではありません。そのIPアドレス。


mysqlをdocker0にもバインドしないのはなぜですか?
ivant 2014年

2
Windowsマシンの場合:-$ docker run -d --name MyWebServer -P httpd
Lokesh S


1
network: hostあなたがいなければ、コンテナからホストに戻ることはできません。コンテナへのホストのみ。これはコンテナの背後にある主要なイデオロギーです。安定性とセキュリティの両方の理由で隔離されています。
FreeSoftwareServers

回答:


1970

編集:あなたが使用している場合はドッカー-ため-MACドッカー-ため、Windowsの 18.03+を、ちょうどホスト使用してMySQLサービスへの接続host.docker.internal(の代わりに127.0.0.1、あなたの接続文字列で)。

Docker 18.09.3以降、これはDocker-for-Linuxでは機能しません。修正は月に8日、2019年に提出されましたし、うまくいけば、コードベースにマージされます。それまでは、qoomonの回答に記載されているように、コンテナーを使用することで回避できます

2020-01:ある程度の進歩がありました。すべてがうまくいけば、これはDocker 20.04に到達するはずです。


TLDR

コマンドで使用--network="host"し、DockerコンテナでDockerホストをポイントします。docker run127.0.0.1

注:このモードは、ドキュメントに従って LinuxのDockerでのみ機能します


Dockerコンテナーのネットワークモードに関する注意

Dockerは、コンテナーの実行時にさまざまなネットワークモードを提供します。選択したモードに応じて、Dockerホストで実行されているMySQLデータベースに異なる方法で接続します。

docker run --network = "bridge"(デフォルト)

Dockerは、docker0デフォルトで名前が付けられたブリッジを作成します。DockerホストとDockerコンテナーの両方がそのブリッジにIPアドレスを持っています。

Dockerホストで次のように入力sudo ip addr show docker0すると、次のような出力が得られます。

[vagrant@docker:~] $ sudo ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    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
    inet6 fe80::5484:7aff:fefe:9799/64 scope link
       valid_lft forever preferred_lft forever

だからここに私のドッカーホストは上のIPアドレス172.17.42.1を持っていますdocker0ネットワークインターフェイスのます。

ここで、新しいコンテナーを起動してシェルを取得しdocker run --rm -it ubuntu:trusty bashます。コンテナータイプ内で、ip addr show eth0メインのネットワークインターフェイスの設定方法を確認します。

root@e77f6a1b3740:/# ip addr show eth0
863: eth0: <BROADCAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 66:32:13:f0:f1:e3 brd ff:ff:ff:ff:ff:ff
    inet 172.17.1.192/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6432:13ff:fef0:f1e3/64 scope link
       valid_lft forever preferred_lft forever

ここで私のコンテナはIPアドレスを持っています172.17.1.192。次に、ルーティングテーブルを確認します。

root@e77f6a1b3740:/# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         172.17.42.1     0.0.0.0         UG    0      0        0 eth0
172.17.0.0      *               255.255.0.0     U     0      0        0 eth0

そのため、DockerホストのIPアドレスが172.17.42.1デフォルトルートとして設定され、コンテナからアクセスできます。

root@e77f6a1b3740:/# ping 172.17.42.1
PING 172.17.42.1 (172.17.42.1) 56(84) bytes of data.
64 bytes from 172.17.42.1: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.42.1: icmp_seq=2 ttl=64 time=0.201 ms
64 bytes from 172.17.42.1: icmp_seq=3 ttl=64 time=0.116 ms

docker run --network = "host"

または、ネットワーク設定をに設定しhostてDockerコンテナーを実行することもできます。このようなコンテナーは、Dockerホストとネットワークスタックを共有し、コンテナーの観点から見るとlocalhost(または127.0.0.1)、Dockerホストを参照します。

Dockerコンテナーで開いているポートはすべて、Dockerホストで開かれることに注意してください。そして、またはオプションを必要とせずに-p-P docker run

私のドッカーホストのIP構成:

[vagrant@docker:~] $ ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

ホストモードのDockerコンテナーから:

[vagrant@docker:~] $ docker run --rm -it --network=host ubuntu:trusty ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:98:dc:aa brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fe98:dcaa/64 scope link
       valid_lft forever preferred_lft forever

ご覧のとおり、DockerホストとDockerコンテナーはまったく同じネットワークインターフェイスを共有しているため、同じIPアドレスを持っています。


コンテナーからMySQLへの接続

ブリッジモード

ブリッジモードのコンテナからdockerホストで実行されているMySQLにアクセスするには、MySQLサービスが172.17.42.1IPアドレスで接続をリッスンしていることを確認する必要があります。

そのためには、必ずどちらか持たせるbind-address = 172.17.42.1か、bind-address = 0.0.0.0MySQLの設定ファイル(my.cnfファイル)で。

ゲートウェイのIPアドレスで環境変数を設定する必要がある場合は、コンテナで次のコードを実行できます。

export DOCKER_HOST_IP=$(route -n | awk '/UG[ \t]/{print $2}')

次に、アプリケーションで、DOCKER_HOST_IP環境変数を使用してMySQLへの接続を開きます。

注:bind-address = 0.0.0.0 MySQLサーバーを使用する場合、すべてのネットワークインターフェースで接続をリッスンします。これは、MySQLサーバーにインターネットからアクセスできることを意味します。それに応じてファイアウォールルールを設定してください。

注2:bind-address = 172.17.42.1 MySQLサーバーを使用している場合、への接続をリッスンしません127.0.0.1。MySQLに接続するDockerホストで実行されるプロセスは、172.17.42.1IPアドレスを使用する必要があります。

ホストモード

ホストモードのコンテナーからdockerホストで実行されているMySQLにアクセスするにbind-address = 127.0.0.1は、MySQL構成を維持でき127.0.0.1、コンテナーから接続するだけで済みます。

[vagrant@docker:~] $ docker run --rm -it --network=host mysql mysql -h 127.0.0.1 -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 36
Server version: 5.5.41-0ubuntu0.14.04.1 (Ubuntu)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

注:使用mysql -h 127.0.0.1しないでくださいmysql -h localhost。そうしないと、MySQLクライアントはUNIXソケットを使用して接続しようとします。


8
こんな細かい回答ありがとうございます!私が収集したものから、ホストモードを使用することが、localhostを介してこの機能を取得する唯一の方法です。私は試していませんが、共通の「localhost」を提供する独自のブリッジを介してコンテナを接続する別のネットワークを作成できると思います。
ベン

26
OSXユーザーへの注意:最初に「docker-machine ssh default」を使用してdocker仮想マシン(boot2docker)にログインし、次に「sudo ip addr show docker0」を実行します。そこからトーマスの指示を続けてください。
チャーリーダルサス

30
私はMac用のDockerを実行していますが、172.14.41.12、docker0はもうありません。それはゲートウェイとして172.17.0.1であり、さらにそれを行うことはできませんtelnet 172.17.0.1 3306
zx1986

26
-v /var/run/mysqld/mysqld.sock:/tmp/mysql.sockこのようにネットワーク接続する代わりに、mysqlソケットをコンテナにマウントできます。
2016

8
MacでDockerを実行していて、boot2dockerを使用していないため、docker0インターフェイスがない場合、誰かが状況に対処できますか?
TheJKFever 2017

350

macOSおよびWindowsの場合

Docker v 18.03以降(2018年3月21日以降)

host.docker.internal内部IPアドレスを使用するか、ホストが使用する内部IPアドレスに解決される特別なDNS名に接続します。

Linuxのサポートは保留中https://github.com/docker/for-linux/issues/264

以前のバージョンのDockerがインストールされたMacOS

Docker for Mac v 17.12からv 18.02

上記と同じですが、docker.for.mac.host.internal代わりに使用します。

Docker for Mac v 17.06からv 17.11

上記と同じですが、docker.for.mac.localhost代わりに使用します。

Docker for Mac 17.05以下

Dockerコンテナからホストマシンにアクセスするには、ネットワークインターフェースにIPエイリアスをアタッチする必要があります。好きなIPをバインドできます。他のIPには使用しないようにしてください。

sudo ifconfig lo0 alias 123.123.123.123/24

次に、サーバーが上記のIPまたはをリッスンしていることを確認します0.0.0.0。localhost 127.0.0.1でリッスンしている場合は、接続を受け入れません。

次に、DockerコンテナーをこのIPにポイントするだけで、ホストマシンにアクセスできます!

テストするにはcurl -X GET 123.123.123.123:3000、コンテナーの内部などを実行します。

エイリアスは再起動のたびにリセットされるため、必要に応じて起動スクリプトを作成します。

ソリューションとその他のドキュメント:https : //docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


5
素晴らしくて感謝しています。これは私にとってコンテナ内で機能しました。 mysql -uroot -hdocker.for.mac.localhost
リチャードフランク

1
docker.for.mac.localhostはまさに私が探していたものです。しかし、これは同時に地獄のように汚いです。dockerでは、フックdocker.for.mac.localhostがMacだけでなく、すべてのオペレーティングシステムに有効な一般的なdocker内部名であると予想されます。しかし、開発目的ではこれで十分です。
99Sono

例えば9093で公開されているポートにアクセスするにはどうすればよいですか。docker.for.mac.localhost 9093にtelnetしようとしています。その到達不能ですが、docker.for.mac.localhostにpingを実行すると、到達可能です。ここに何か不足していますか?
アキレウス2017

1
localhostのサブドメインの使用を禁止するRFCがあるため、コンテナーからのホスト解決にはdocker.for.mac.localhost(まだ有効)の代わりにDNS名docker.for.mac.host.internalを使用する必要があります。tools.ietf.org/html/draft-west-let-localhost-be-localhost-06を参照してください。
Jya

これは私にはうまくいきません。Iのdocker run -e HOSTNAME= docker.for.mac.host.internal 場合、コンテナは作成されますが、何も起こりません。その後、crtl + Cを実行する必要があります。--net=host -e HOSTNAME=localhost少なくともコンテナが実行され、それがサービスIの必要性を見つけることができないことに文句(MySQLのデシベル)。
ホルヘオルピネル2018年

83

上記の投稿と同様のハックを行って、ローカルIPを取得してコンテナ内のエイリアス名(DNS)にマッピングします。主な問題は、LinuxとOSXの両方でホストIPアドレスで機能する単純なスクリプトを動的に取得することです。両方の環境で動作するこのスクリプトを実行しました("$LANG" != "en_*"構成済みのLinuxディストリビューションでも)。

ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1

したがって、Docker Composeを使用すると、完全な構成は次のようになります。

起動スクリプト(docker-run.sh)

export DOCKERHOST=$(ifconfig | grep -E "([0-9]{1,3}\.){3}[0-9]{1,3}" | grep -v 127.0.0.1 | awk '{ print $2 }' | cut -f2 -d: | head -n1)
docker-compose -f docker-compose.yml up

docker-compose.yml

myapp:
  build: .
  ports:
    - "80:80"
  extra_hosts:
    - "dockerhost:$DOCKERHOST"

次に、コードhttp://localhosthttp://dockerhostに変更します。

DOCKERHOSTスクリプトをカスタマイズする方法のより高度なガイドについては、この投稿を見て、そのしくみの説明をご覧ください。


1
ユースケースによっては、DOCKERHOSTDockerコンテナーがローカルに接続する必要のあるサービスで、「localhost」または0.0.0.0の代わりにここで値を使用するだけで済む場合もあります。
エンダーランド2017年

2
:私は少しカスタムネットワークと互換性があるようにあなたのソリューションを変更した<NETWORK-NAME>は、可能性ブリッジドッカ-コン(通常で定義されているか、ネットワークの名前パス名- NETWORK_NAME)。export DOCKERHOST=$(docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' <NETWORK-NAME> | awk -F "/" 'NR==1{print $1}')
dieresys 2017

1
コメントを追加する必要があります:dockerhostdb接続のホストとして使用します(通常、構成localhostファイルで置き換えます)。
ジャスティン

奇妙なソリューションですが、xdebugをphp cliを使用してdockerで動作させる唯一の方法
Eddie

haproxyでこのソリューションを実行すると、Aclは動作を停止しました。なぜか?
HyukHyukBoi

41

これは、アプリが接続できることを期待しているコードやネットワークに触れることなく、NGINX / PHP-FPMスタックで私にとってうまくいきました localhost

mysqld.sockホストからコンテナ内にマウントします。

mysqlを実行しているホストでmysql.sockファイルの場所を見つけます。
netstat -ln | awk '/mysql(.*)?\.sock/ { print $9 }'

そのファイルをdockerで想定されている場所にマウントします。
docker run -v /hostpath/to/mysqld.sock:/containerpath/to/mysqld.sock

mysqld.sockの可能な場所:

/tmp/mysqld.sock
/var/run/mysqld/mysqld.sock 
/var/lib/mysql/mysql.sock
/Applications/MAMP/tmp/mysql/mysql.sock # if running via MAMP

2
これは、Mysqlを外部に公開しない(ファイアウォールを使用していない場合)よりクリーンなソリューションです。
user1226868 2015

5
ソケットはブロックする頻度が高く、奇妙な動作を引き起こす可能性があるため、TCPほど拡張性がありません。可能な限りTCPを使用してください。
Joel E Salas

3
@JoelESalasその主張の出典はありますか?
プライベート

これが最も簡単な解決策であることがわかりました。user833482を高く評価しています!StackOverflowにもっと頻繁に貢献する必要があります。
プライベート

2
@JoelESalas間違いだと思います。mysqlクライアントライブラリは、localhostに実際に接続するのではなく、localhostに接続するときにデフォルトでUNIXソケットを使用します。UNIXソケットは、TCPスタックとルーティングのオーバーヘッドを回避し、より高速に実行する必要があります。
Mコンラッド

25

host.docker.internalがすべてのプラットフォームで機能するまで、手動で設定しなくても、NATゲートウェイとして機能する私のコンテナを使用できます。

https://github.com/qoomon/docker-host


5
私はこれがDocker for Windows 19.03.2とWindowsコンテナーで動作しないことを確認できます。
KMC、

それを修正する方法はありますか?(私はWindowsユーザーではありません)
qoomon

環境がmysqlが使用するポートをブロックしない場合は、ホストされているコンピューター名でサーバーを参照できます。したがって、接続文字列では、コンピュータ名をサーバー名として使用します。
KMC、

24

Linuxのソリューション(カーネル> = 3.6)。

ローカルホストサーバーには、IPアドレス172.17.0.1のデフォルトのdockerインターフェイスdocker0があります。コンテナはデフォルトのネットワーク設定--net = "bridge"で開始しました。

  1. docker0インターフェイスのroute_localnetを有効にします。
    $ sysctl -w net.ipv4.conf.docker0.route_localnet=1
  2. このルールをiptablesに追加します。
    $ iptables -t nat -I PREROUTING -i docker0 -d 172.17.0.1 -p tcp --dport 3306 -j DNAT --to 127.0.0.1:3306
    $ iptables -t filter -I INPUT -i docker0 -d 127.0.0.1 -p tcp --dport 3306 -j ACCEPT
  3. 「%」からのアクセス権を持つmysqlユーザーを作成します-つまり、localhostを除くすべてのユーザーから:
    CREATE USER 'user'@'%' IDENTIFIED BY 'password';
  4. スクリプトでmysql-serverアドレスを172.17.0.1に変更します。


カーネルのドキュメント から:

route_localnet-ブール値:ルーティング時にループバックアドレスを火星の送信元または宛先と見なさないでください。これにより、ローカルルーティングのために127/8を使用できるようになります(デフォルトはFALSE)。


1
2番目のiptableコマンドの目的は何ですか?最初の1つは、172.17.0.1:3306に一致するすべてのTCP宛先を127.0.0.1:3306に書き換えることですが、2番目のiptableコマンドが必要なのはなぜですか?
Patrick

17

Windows 10のソリューション

Docker Community Edition 17.06.0-ce-win18 2017-06-28(安定版)

ホストのDNS名を使用docker.for.win.localhostして、内部IPに解決できます。(警告されたいくつかのソースに警告しますwindowsが、それはすべきですwin

概要
私はDockerコンテナーからとを実行していたローカルホストに接続するなど、同様のことを行う必要がAzure Storage EmulatorありましたCosmosDB Emulator

Azure Storage Emulatorデフォルトで127.0.0.1をリッスンしますが、IPのバインドも変更できますが、デフォルト設定で機能するソリューションを探していました。

これは、DockerコンテナーからSQL Serverおよびへの接続にも機能しIISます。どちらも、デフォルトのポート設定を使用してホストでローカルに実行されます。


13

非常にシンプルかつ迅速に、ifconfig(linux)またはipconfig(windows)でホストIPを確認し、

docker-compose.yml

version: '3' # specify docker-compose version

services:
  nginx:
    build: ./ # specify the directory of the Dockerfile
    ports:
      - "8080:80" # specify port mapping
    extra_hosts:
      - "dockerhost:<yourIP>"

これにより、コンテナーはホストにアクセスできるようになります。DBにアクセスするときは、前に指定した名前を使用してください。この場合は、「dockerhost」と、DBが実行されているホストのポートです。


HaProxyでは、このソリューションは何らかの理由でACLの機能を停止しました。デフォルト設定のみが機能しています。
HyukHyukBoi

1
Linuxシステムで動作する唯一のソリューション。+1
Rafik Farhad

11

Windows 10 HomeでDocker Toolboxを使用した場合、私にはどの回答も機能しませんでしたが、10.0.2.2は、このアドレスでVMにホストを公開するVirtualBoxを使用しているため、機能しました。


2
できます。--network = hostを指定する必要はありません。ホストのデフォルトIPとして10.0.2.2が設定されているように見えます。ありがとう。
TheManish

しかし、この静的IPをWindowsとMacのすべてのバージョンに使用できますか?スクリプトを使用して複数のプラットフォームでどのように処理できますか?
151291

これでうまくいきました。ホスト(Windows)でipconfigを実行し、IPアドレスを取得しますEthernet adapter vEthernet (DockerNAT)
Kihats

10

Windowsの場合は、ブリッジネットワークドライバーを使用していると仮定して、MySQLをhyper-vネットワークインターフェースのIPアドレスに具体的にバインドする必要があります。

これは、通常は非表示のC:\ ProgramData \ MySQLフォルダーにある設定ファイルを介して行われます。

0.0.0.0へのバインドは機能しません。必要なアドレスはDocker構成にも表示され、私の場合は10.0.75.1でした。


3
あなたはメダルに値します!私はこれに2日間取り組んできました。手伝ってくれてありがとう!
マイケル

1
私も2日間これに取り組んでいました。これは私がそれを言及したと私が見つけた唯一の場所です。Microsoftは、Dockerコンテナー内からMSSQLに接続することについて話しているとき、これについて完全に沈黙しています。それは彼らが今まで彼らがそれを彼ら自身で働かせたかどうか疑問に思います!
Contango 2017年

8

編集:結局、GitHubでコンセプトのプロトタイプを作成しました。チェックアウト: https : //github.com/sivabudh/system-in-a-box


まず、私の答えは、Macを使用するグループとLinuxを使用するグループという2つのグループに向けられています。

ホストネットワークモードは、Mac上では動作しません。IPエイリアスを使用する必要があります。https//stackoverflow.com/a/43541681/2713729を参照してください。

ホストネットワークモードとは何ですか?参照:https : //docs.docker.com/engine/reference/run/#/network-settings

第二に、Linuxを使用しているあなたの人々のために(私の直接の経験は、Ubuntuの14.04 LTSでだったと私は生産に16.04 LTSへのアップグレードをすぐにだ)はい、あなたがに接続するサービスがドッカーコンテナ内で実行することができますlocalhost上で実行されているサービスDockerホスト(ラップトップなど)。

どうやって?

重要なのは、Dockerコンテナーを実行するときに、ホストモードで実行する必要があることです。コマンドは次のようになります。

docker run --network="host" -id <Docker image ID>

あなたが行う場合にはifconfig(あなたが必要となりますapt-get install net-toolsため、コンテナifconfig、コンテナ内の呼び出し可能にする)は、ネットワークインタフェースがドッカーホスト上の1(例えば、ノートパソコン)と同じであることがわかります。

私はMacユーザーですが、ParallelsでUbuntuを実行しているため、Macを使用しても不利ではないことに注意してください。;-)

これは、NGINXコンテナをで実行されているMySQLに接続する方法ですlocalhost


1
ホストモードはOSネットワークスタックを使用するため、パフォーマンスが向上することに注意してください。
sivabudh 2017

2
とても良い点があります。コンテナからホストサービスに未使用のIPで接続することは可能ですが、docs.docker.com/docker-for-mac/networkingをアタッチしてください。快適な解決策ではありません...しかしうまくいきます。
XavierHuppé2017

ここに良いもの。を使用してコンテナ内に入ると--network="host"、たとえばホストmysqlにどのように接続しますか
マイケル

1
@Buccleuch使用してくださいlocalhost。私のGitHubソースコードを確認してください:github.com/sivabudh/system-in-a-box/blob/master/dj_host_docker/…。を検索すると'HOST'、Postgresqlに接続するために127.0.0.1が表示されます。
sivabudh

@ user833482に従ってボリュームをマウントすることで、ホストmysqlデータベースにアクセスできました。もちろん、mysql-clientとserverをdockerコンテナーにインストールした後です。
マイケル

7

Mac OSXの最も簡単なソリューション

MacのIPアドレスを使用するだけです。Macでは、これを実行してIPアドレスを取得し、コンテナー内から使用します。

$ ifconfig | grep 'inet 192'| awk '{ print $2}'

Macまたは別のDockerコンテナーでローカルに実行されているサーバーが0.0.0.0をリッスンしている限り、Dockerコンテナーはそのアドレスに到達できます。

0.0.0.0でリッスンしている別のDockerコンテナーにアクセスしたいだけの場合は、172.17.0.1を使用できます。


1
Docker for Macがdocker.for.mac.host.internalホスト名を公開するようになりました。
マット

5

これは実際の質問に対する回答ではありません。これは私が同様の問題を解決した方法です。ソリューションは完全に以下から得られます:コンテナが通信できるようにDockerコンテナネットワークを定義します。ニックラボーイのおかげで

コンテナー間でREST呼び出しを実行する可能性がある他のユーザーのために、これをここに残します。質問への回答:docker環境でlocalhostの代わりに何を使用しますか?

ネットワークがどのように見えるかを取得する docker network ls

新しいネットワークを作成する docker network create -d my-net

最初のコンテナーを開始する docker run -d -p 5000:5000 --network="my-net" --name "first_container" <MyImage1:v0.1>

最初のコンテナのネットワーク設定を確認してくださいdocker inspect first_container。「ネットワーク」:「my-net」が必要です

2番目のコンテナーを開始する docker run -d -p 6000:6000 --network="my-net" --name "second_container" <MyImage2:v0.1>

2番目のコンテナのネットワーク設定を確認してくださいdocker inspect second_container。「ネットワーク」:「my-net」が必要です

あなたの第二の容器にはssh docker exec -it second_container shdocker exec -it second_container bash

2番目のコンテナの内側では、最初のコンテナにをpingできますping first_container。また、などのコード呼び出しはhttp://localhost:5000http://first_container:5000


まさに私が探していたもの。ありがとう:D
Simar Singh

5

ウィンドウの場合、

私は春の構成でデータベースのURLを変更しました: spring.datasource.url=jdbc:postgresql://host.docker.internal:5432/apidb

次に、イメージをビルドして実行します。それは私のために働いた。


興味深い....
フィル

私にとっては動作しません。私はMacを使用していて、phpコンテナからlocalhost mysqlに接続しようとしています。何か案が ?
A. Zalonis

4

Thomasleveilからの回答に同意しません。

mysqlを172.17.42.1にバインドすると、他のプログラムがホスト上のデータベースを使用してそれに到達できなくなります。これは、すべてのデータベースユーザーがドッキングされている場合にのみ機能します。

mysqlを0.0.0.0にバインドすると、dbが外部に開かれます。これは、実行するのが非常に悪いことであるだけでなく、元の質問の作成者が望んでいることにも反しています。彼は「MySqlはlocalhostで実行されており、ポートを外部に公開していないため、localhostにバインドされている」と明確に述べています。

ivantからのコメントに答えるには

「mysqlをdocker0にもバインドしないのはなぜですか?」

これは不可能です。mysql / mariadbのドキュメントには、複数のインターフェースにバインドすることはできないと明示的に記載されています。バインドできるのは0、1、またはすべてのインターフェースのみです。

結論として、私はdockerコンテナーからホスト上の(localhostのみ)データベースに到達する方法を見つけていません。これは非常に一般的なパターンのようですが、どうすればよいかわかりません。


4
Dockerホストからは、172.17.42.1アドレスを使用してMySQLサーバーに接続できます。しかし、あなたのメモはそうでなければ正しいです。麻生、hostMySQLサーバーをバインドした127.0.0.1ままコンテナーを接続できるネットワークモードで回答を編集しました
Thomasleveil

いいえ、私が言ったように、mysqlがlocalhostにバインドされている場合、172.17.42.1に接続できません。
オーゼル2015年

4
「mysqlを172.17.42.1にバインドすると、他のプログラムがホスト上のデータベースを使用してそれに到達できなくなります。」-それは真実ではありません。他のプログラムはmysqlを使用できます。localhost/ 127.0.0.1ではなく172.17.42.1に接続する必要があります。
0x89

この回答の問題の解決策は、通常、MySQLサーバーをバインドしてから0.0.0.0ファイアウォールを設定して、インターネットからデータベースにアクセスできないようにすることです。
2017年

4

これが私の解決策です:それは私のケースで機能します

  • #bind-address = 127.0.0.1 /etc/mysql/mysql.conf.dのコメントにより、ローカルmysqlサーバーをパブリックアクセスに設定します。

  • MySQLサーバーを再起動します sudo /etc/init.d/mysql restart

  • 次のコマンドを実行して、任意のホストにユーザーrootアクセスをオープン mysql -uroot -proot GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION; FLUSH PRIVILEGES;

  • shスクリプトの作成:run_docker.sh

    #!bin / bash

    HOSTIP = `ip -4 addr show scope global dev eth0 | grep inet | awk '{print \ $ 2}' | カット-d / -f 1`


      docker run -it -d --name web-app \
                  --add-host = local:$ {HOSTIP} \
                  -p 8080:8080 \
                  -e DATABASE_HOST = $ {HOSTIP} \
                  -e DATABASE_PORT = 3306 \
                  -e DATABASE_NAME = demo \
                  -e DATABASE_USER = root \
                  -e DATABASE_PASSWORD = root \
                  sopheamak / springboot_docker_mysql

  
  • docker-composerで実行する

    バージョン: '2.1'

    サービス:
    tomcatwar: extra_hosts: -「local:10.1.2.232」 イメージ:sopheamak / springboot_docker_mysql
    ポート: -8080:8080 環境: -DATABASE_HOST = local -DATABASE_USER = root -DATABASE_PASSWORD = root -DATABASE_NAME = demo -DATABASE_PORT = 3306


4

いくつかの解決策が思い浮かびます:

  1. 最初に依存関係をコンテナに移動します
  2. 他のサービスを外部からアクセス可能にし、その外部IPでそれらに接続します
  3. ネットワークを分離せずにコンテナーを実行する
  4. ネットワーク経由の接続を避け、代わりにボリュームとしてマウントされているソケットを使用します

これがそのままでは機能しない理由は、コンテナがデフォルトで独自のネットワーク名前空間で実行されるためです。つまり、localhost(またはループバックインターフェイスを指す127.0.0.1)はコンテナーごとに一意です。これに接続すると、コンテナー自体に接続されます。Dockerの外部または別のDockerコンテナーの内部で実行されているサービスには接続されません。

オプション1:依存関係をコンテナに移動できる場合は、最初にこれを行います。他のユーザーが独自の環境でコンテナーを実行しようとするときに、アプリケーションスタックを移植可能にします。また、移行されていない他のサービスが引き続きポートに到達できるホスト上のポートを公開することもできます。ポートをdockerホストのlocalhostインターフェースに-p 127.0.0.1:3306:3306公開して、公開されたポートのような構文で外部からアクセスできないようにすることもできます。

オプション2:コンテナーの内部からホストIPアドレスを検出する方法はさまざまですが、それぞれが機能するシナリオは限られています(たとえば、Docker for Macが必要です)。最も移植性の高いオプションは、環境変数や構成ファイルなどを使用して、ホストIPをコンテナーに挿入することです。

docker run --rm -e "HOST_IP=$(ip r s 0/0 | awk '{print $3}')" ...

これには、サービスがその外部インターフェースでリッスンしている必要がありますが、これはセキュリティ上の問題となる可能性があります。コンテナー内からホストIPアドレスを取得する他の方法については、この投稿を参照してください

オプション3:ネットワーク分離なしで実行、つまりで実行すると--net host、アプリケーションがホストネットワーク名前空間で実行されます。これはコンテナーの分離が少なく、DNSを使用する共有Dockerネットワーク経由で他のコンテナーにアクセスできないことを意味します(代わりに、公開されたポートを使用して他のコンテナー化されたアプリケーションにアクセスする必要があります)。ただし、ホスト上127.0.0.1でのみリッスンしているホスト上の他のサービスにアクセスする必要があるアプリケーションの場合、これは最も簡単なオプションです。

オプション4:さまざまなサービスで、ファイルシステムベースのソケットを介したアクセスも許可されます。このソケットはバインドマウントボリュームとしてコンテナーにマウントできるため、ネットワークを経由せずにホストサービスにアクセスできます。Dockerエンジンへのアクセスについて/var/run/docker.sockは、コンテナーへのマウントの例をよく目にします(そのコンテナールートにホストへのアクセス権を付与します)。mysqlでは、次のようなことを試して-v /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysql.sockからlocalhost、mysqlが変換するソケットに接続できます。


3

高山のイメージを使用してホストIPを取得できます

docker run --rm alpine ip route | awk 'NR==1 {print $3}'

コマンドを実行するために常に高山を使用しているので、これはより一貫性があります。

マリアーノの答えと同様に、同じコマンドを使用して環境変数を設定できます

DOCKER_HOST=$(docker run --rm alpine ip route | awk 'NR==1 {print $3}') docker-compose up

3

Linuxの場合、localhostサービスがバインドするインターフェースを変更できません

解決しなければならない2つの問題があります

  1. ホストのIPを取得する
  2. ローカルホストサービスをDockerで利用できるようにする

最初の問題はqoomonの -hostイメージ、他の回答で示されているように、ます。

このコンテナーにアクセスするには、このコンテナーを他のコンテナーと同じブリッジネットワークに追加する必要があります。コンテナ内のターミナルを開き、pingできることを確認しますdockerhost

bash-5.0# ping dockerhost
PING dockerhost (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.523 ms

さて、難しい問題で、Dockerがサービスにアクセスできるようにします。

telnetを使用して、ホストのポートにアクセスできるかどうかを確認できます(これをインストールする必要がある場合があります)。

問題は、コンテナがSSHなどのすべてのインターフェースにバインドするサービスにしかアクセスできないことです。

bash-5.0# telnet dockerhost 22
SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.3

ただし、localhostにのみバインドされたサービスにはアクセスできなくなります。

bash-5.0# telnet dockerhost 1025
telnet: can't connect to remote host (172.20.0.2): Connection refused

ここでの適切な解決策は、サービスをドッカーズブリッジネットワークにバインドすることです。ただし、この回答では、これを変更することはできないと想定しています。したがって、代わりにを使用しますiptables

まず、Dockerがで使用しているブリッジネットワークの名前を見つける必要がありますifconfig。名前のないブリッジを使用している場合、これは単にになりますdocker0。ただし、名前付きネットワークを使用している場合は、br-代わりにそのDockerが使用されます。私のですbr-5cd80298d6f4

このブリッジの名前を取得したら、このブリッジからローカルホストへのルーティングを許可する必要があります。これは、セキュリティ上の理由からデフォルトで無効になっています。

sysctl -w net.ipv4.conf.<bridge_name>.route_localnet=1

次に、 iptablesルール。コンテナーはDockerブリッジネットワークのポートにしかアクセスできないので、サービスがこのネットワークのポートに実際にバインドされているように見せかけます。

これを行うには、すべてのリクエストを<docker_bridge>:portに転送しますlocalhost:port

iptables -t nat -A PREROUTING -p tcp -i <docker_bridge_name> --dport <service_port> -j DNAT --to-destination 127.0.0.1:<service_port>

たとえば、ポート1025のサービスの場合

iptables -t nat -A PREROUTING -p tcp -i br-5cd80298d6f4 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025

これで、コンテナーからサービスにアクセスできるようになります。

bash-5.0# telnet dockerhost 1025
220 127.0.0.1 ESMTP Service Ready

1
これは、@ ray-dが前述したものと同じですが、うまく説明されています。ありがとうございました!さらに、docker-composeを使用する場合、docker0インターフェースに到着するすべてのパケットのPREROUTINGチェーンにDNATルールも追加する必要がありました。sysctl -w net.ipv4.conf.docker0.route_localnet=1およびiptables -t nat -A PREROUTING -p tcp -i docker0 --dport 1025 -j DNAT --to-destination 127.0.0.1:1025
arvindd

3

ゲートウェイを知る必要があります!ローカルサーバーでの私のソリューションは0.0.0.0:8000、それをで公開し、サブネットで dockerを実行することでした実行し、コンテナーを次のように。

docker network create --subnet=172.35.0.0/16 --gateway 172.35.0.1 SUBNET35
docker run -d -p 4444:4444 --net SUBNET35 <container-you-want-run-place-here>

だから、今あなたはループバックにアクセスすることができます http://172.35.0.1:8000


3

これを試して:

version: '3.5'
services:
  yourservice-here:
    container_name: container_name
    ports:
      - "4000:4000"
    extra_hosts: # <---- here
      - localhost:192.168.1.202
      - or-vitualhost.local:192.168.1.202

取得する192.168.1.202には、ifconfig

これでうまくいきました。この助けを願っています!


2

CGroupsと名前空間は、コンテナエコシステムで主要な役割を果たしています。

名前空間は分離の層を提供します。各コンテナーは個別の名前空間で実行され、そのアクセスはその名前空間に制限されます。Cgroupは各コンテナーのリソース使用率を制御しますが、Namespaceはプロセスがそれぞれのリソースを表示してアクセスできるものを制御します。

これは、従うことができるソリューションアプローチの基本的な理解です。

ネットワーク名前空間を使用する

コンテナーがイメージからスポーンすると、ネットワークインターフェイスが定義され、作成されます。これにより、コンテナに一意のIPアドレスとインターフェースが付与されます。

$ docker run -it alpine ifconfig

ネームスペースをホストに変更することにより、コンテナネットワークはそのインターフェースに分離されたままではなく、プロセスはホストマシンのネットワークインターフェースにアクセスできます。

$ docker run -it --net=host alpine ifconfig

プロセスがポートでリッスンする場合、それらはホストインターフェースでリッスンされ、コンテナにマップされます。

PID名前空間を使用 するPid名前空間を変更することで、コンテナーは通常のスコープを超えて他のプロセスと対話できます。

このコンテナは独自の名前空間で実行されます。

$ docker run -it alpine ps aux

ネームスペースをホストに変更することにより、コンテナはシステムで実行されている他のすべてのプロセスも確認できます。

$ docker run -it --pid=host alpine ps aux

名前空間の共有

これは、脆弱性や盗聴者への容易なアクセスが発生する可能性のあるコンテナセキュリティモデルから抜け出すため、本番環境でこれを行うには不適切な方法です。これは、ツールをデバッグし、コンテナセキュリティの抜け穴を過小評価するためのものです。

最初のコンテナはnginxサーバーです。これにより、新しいネットワークとプロセスの名前空間が作成されます。このコンテナーは、新しく作成されたネットワークインターフェイスのポート80にバインドされます。

$ docker run -d --name http nginx:alpine

別のコンテナがこの名前空間を再利用できるようになりました、

$ docker run --net=container:http mohan08p/curl curl -s localhost

また、このコンテナは、共有コンテナ内のプロセスとのインターフェースを見ることができます。

$ docker run --pid=container:http alpine ps aux

これにより、アプリケーションを変更したり再起動したりせずに、コンテナーにより多くの特権を与えることができます。同様に、ホスト上のmysqlに接続し、アプリケーションを実行およびデバッグできます。しかし、この方法で行くことはお勧めしません。それが役に立てば幸い。


1

Windowsマシンの場合:-

以下のコマンドを実行して、ビルド時にDockerポートをランダムに公開します

$docker run -d --name MyWebServer -P mediawiki

ここに画像の説明を入力してください

ここに画像の説明を入力してください

上記のコンテナリストで、32768として割り当てられているポートを確認できます。

localhost:32768 

あなたはmediawikiページを見ることができます


5
この回答は一部のユーザーに役立つ情報を提供する可能性がありますが、それは間違った方法です!それは、ホストマシンからコンテナで実行されているサービスにアクセスすることです。ただし、問題は、コンテナーからホストで実行されているサービスへのアクセスに関するものでした。
einjohn


1

MySQLでコンテナーのIPのユーザーを作成することで解決しました。

$ sudo mysql<br>
mysql> create user 'username'@'172.17.0.2' identified by 'password';<br>
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on database_name.* to 'username'@'172.17.0.2' with grant option;<br>
Query OK, 0 rows affected (0.00 sec)

$ sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
<br>bind-address        = 172.17.0.1

$ sudo systemctl restart mysql.service

次に、コンテナで: jdbc:mysql://<b>172.17.0.1</b>:3306/database_name


これが最も簡単なソリューションです。それは私にとってはうまくいき、私は多くのことを紹介しました
ソフィアアルフレッド

-1

私が行う方法は、ホストIPを環境変数としてコンテナーに渡すことです。次に、コンテナはその変数によってホストにアクセスします。


これをどのように行うか説明できますか?私はこのアプローチを試みましたが、あまり成功しませんでした
kmjb

`docker run -i -t -e HOST = 10.145.2.123 ubuntu root @ ce2a843da3ee:/ tmp#./telnet $ HOST 22 Trying 10.145.2.123 ... 10.145.2.123に接続しました。エスケープ文字は「^]」です。SSH-2.0-OpenSSH_7.4`
F.カム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.