Dockerコンテナー内からDockerホストのIPアドレスを取得する方法


358

タイトル通り。DockerがホストするIPアドレスとポートマップをホストからコンテナーに取得し、コンテナー内で取得できるようにする必要があります。


この情報の使用方法について詳しく教えてください。「docker hosts」とおっしゃっていましたが、複数のホストでDockerを実行していますか?コンテナがホストとポートマップのIPアドレスを認識したら、何をしますか?
アンディ14

DockerホストのIPアドレスをDockerコンテナーに渡す最も簡単な方法は、コンテナー内で「docker container exec」を使用して呼び出す必要があると思います。例えば、busyboxコンテナーの内部からホストにpingを実行したい場合は、次のように使用します。
SauloAlessandre

回答:


314
/sbin/ip route|awk '/default/ { print $3 }'

@MichaelNealeが気づいたように、DockerfileこのIPはビルド時にハードコードされるため、(ビルド時にのみこのIPが必要な場合を除いて)このメソッドを使用する意味はありません。


49
コンテナーにdockerブリッジ(デフォルト)を使用している場合、これは192.168.1.xなどのホストのIPではなく、172.17.42.1のようなブリッジIPを出力します(ホストがホームNAT上にあると想定しています)。@Magno Torresの回答を使用することは、192.168.1.xアドレスが必要な場合、おそらくそのような状況で人々が望んでいることです。
Programster

2
そのRUNは期待どおりに機能しません-ビルド時にIPを計算するだけで、その後は永久に静的であり、役に立たなくなります。ビルドホストのIPになります。
Michael Neale

7
@Programster、私は人々がドッカーのホストとコンテナ間の接続を望んでいると想定できます。それがブリッジIPがあなたに与えることができるものです(もちろん、標準の「ホーム」インストールで)。Dockerブリッジの外側にいてもアクセスできない可能性がある場合、なぜ「実際の」ホストIPが必要になるのでしょうか。これは、Dockerをインストールしたばかりで短時間でそれを試してみたいすべての人のためのソリューションです。
2015年

1
@MichaelNealeは、以前と同じように、dockerで開始するほとんどの人がホストとコンテナー間の接続を必要としていると思います。誰かが「適切な」展開を行っている場合、おそらく彼はとにかくdocker bridgeを使用しておらず、カスタムネットワークを使用しており、おそらくすべてのネットワークの癖やDNS(または何か発見)が設定されていることに気付いています。
2015年

1
@spinus-しかし、これは、それが構築されたホストで実行される場合にのみ有効です-その場合、ハードコーディングするか、調べるだけです-これは役に立たない回答であり、多くの誤解を招くでしょう人の-それを削除することをお勧めします。(RUNビット)
Michael Neale

182

バージョン18.03以降host.docker.internal、ホストのIPとして使用できます。

働くMac用ドッカーWindows用ドッカー、そしておそらく他のプラットフォームにも。

これは、docker.for.mac.localhostバージョン17.06以降で利用可能なMac固有の、およびdocker.for.mac.host.internalバージョン17.12以降で利用可能なからのアップデートであり、そのプラットフォームでも引き続き機能する可能性があります。

注意、のようにマックWindowsのドキュメント、これは開発のみを目的としています。

たとえば、ホストに環境変数を設定しています。

MONGO_SERVER=host.docker.internal

私のdocker-compose.ymlファイルには、これがあります:

version: '3'

services:
  api:
    build: ./api
    volumes:
      - ./api:/usr/src/app:ro
    ports:
      - "8000"
    environment:
      - MONGO_SERVER
    command: /usr/local/bin/gunicorn -c /usr/src/app/gunicorn_config.py -w 1 -b :8000 wsgi

2
@allanberry残念ながら、Dockerの人々は、プラットフォームに依存しない方法でこれを行うことを望まない(Dockerコンテナーからローカルマシン上のサービスにアクセスするなど)
Andy

21
Build it once、run itwhereのようなDockerを紹介されましたただし、常にホストシステムも構成する必要があるため、これは実際には誤りです。したがってdocker.for.mac..、ほとんどの場合、会社にはLinuxまたはMacのみの環境がないため、役に立ちません。LinuxとMacとWindowsを使用している開発者がいます。このドメインは、99%が混合ホストOS環境であるため、意味がありません。私はmacOSでコンテナーを開発せず、macOSサーバーにデプロイしません。Linuxに展開します。これは誰もがやっていることです。そうであっても全体のポイントは何ですかdocker.for.mac..
TheFox 2018年

1
@allanberry docker.for.mac.host.internalは、Dockerの有無に関係なく使用できdocker-composeます。構成ファイルで固定ホストを使用したい。IDK、例えば、docker.host.internal常にホストのIPアドレスを指しています。使用しているホストシステムに関係なく。これが、Dockerを使用する全体のポイントです。自律的になりたいのです。ホストシステムとコンテナーの間に別のレイヤーがあるため、macOSではさらにトリッキーであると理解しています。しかし、いずれにせよ、私の意見ではdocker.for.mac.host.internal、あなたが唯一のMacOSのためにそれを使用できるかどう無用です。
TheFox 2018年

1
host.docker.internal 少なくともこのコメントを書いている時点では、Docker for Windowsでも動作します。
joanlofe

1
これは完璧に動作します。私はウィンドウ用のdockerCeとコンテナの1つでjenkinsを実行しています。jenkins内でdockerコマンドを実行したかったのですが、Dockerはクラウドの追加ステップで接続できませんでした。このtcp://host.docker.internal:2375を使用して、 'localhost:2375でデーモンを公開'を有効にすると機能します。多くの時間を節約しました。ありがとう!
Vikash

84

更新:Docker for Macでは、バージョン18.03以降、ホストのIPとしてhost.docker.internalを使用できます。アランベリーの答えを見てください。Docker for Macの以前のバージョンでは、次の回答が役立つ場合があります。

Docker for Macではdocker0ブリッジが存在しないため、ここでの他の回答が機能しない可能性があります。ただし、すべての送信トラフィックは親ホストを介してルーティングされるため、IPに接続しようとする限り、それ自体として認識されます(そして、Dockerコンテナーはそれ自体ではないと考えます)、接続できるはずです。たとえば、これを親マシンの実行から実行する場合:

ipconfig getifaddr en0

これにより、現在のネットワーク上のMacのIPが表示され、Dockerコンテナーもこのアドレスに接続できるはずです。これはもちろん、このIPアドレスが変更された場合の痛みですが、親マシンで次のようなことを行うことにより、コンテナがそれ自体ではないと思われるカスタムループバックIPをMacに追加できます。

sudo ifconfig lo0 alias 192.168.46.49

その後、telnetを使用してdockerコンテナー内から接続をテストできます。私の場合、リモートのxdebugサーバーに接続したいと思いました。

telnet 192.168.46.49 9000

これで、トラフィックが192.168.46.49にアドレス指定されたMacに入ると(そしてコンテナーから出るすべてのトラフィックがMacを通過する場合)、MacはIP自体であると想定します。このIPの使用が終了したら、次のようにループバックエイリアスを削除できます。

sudo ifconfig lo0 -alias 192.168.46.49

注意が必要なことの1つは、トラフィックの宛先がそれ自体であると考える場合、Dockerコンテナーは親ホストにトラフィックを送信しないことです。問題がある場合は、コンテナ内のループバックインターフェイスを確認してください。

sudo ip addr show lo

私の場合、これinet 127.0.0.1/8127.*範囲内のIPを使用できないことを示しています。これ192.168.*が、上の例で使用した理由です。使用するIPが自分のネットワーク上のものと競合しないことを確認してください。


システムの再起動後にこれらのループバック設定をクリーンアップしますか?
Robbo_UK 2017年

@Robbo_UKはい、Macを再起動するとループバックエイリアスは削除されます。
コードコマンダー

1
このホスト名は、Docker for Linuxでは機能しないため、使用しても意味がありません。Linuxでも追加しなかったのはなぜですか?
TheFox 2018

彼らは現時点でそれを調査しています@TheFox:github.com/docker/libnetwork/pull/2348
Ivo Pereira

46

AWSでDockerを実行している場合、ホストのインスタンスメタデータは、コンテナー内から引き続き利用できます。

curl http://169.254.169.254/latest/meta-data/local-ipv4

例えば:

$ docker run alpine /bin/sh -c "apk update ; apk add curl ; curl -s http://169.254.169.254/latest/meta-data/local-ipv4 ; echo"
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.3/community/x86_64/APKINDEX.tar.gz
v3.3.1-119-gb247c0a [http://dl-cdn.alpinelinux.org/alpine/v3.3/main]
v3.3.1-59-g48b0368 [http://dl-cdn.alpinelinux.org/alpine/v3.3/community]
OK: 5855 distinct packages available
(1/4) Installing openssl (1.0.2g-r0)
(2/4) Installing ca-certificates (20160104-r2)
(3/4) Installing libssh2 (1.6.0-r1)
(4/4) Installing curl (7.47.0-r0)
Executing busybox-1.24.1-r7.trigger
Executing ca-certificates-20160104-r2.trigger
OK: 7 MiB in 15 packages
172.31.27.238

$ ifconfig eth0 | grep -oP 'inet addr:\K\S+'
172.31.27.238

これは、AWSを使用するユーザーにとって非常に便利な方法です。これを使用して、Consulエージェントのクライアントとバインドアドレスを構成します。ホストネットワーキングを使用できない状況(Elastic BeanstalkやECSでのコンテナーのデプロイなど)に最適です。
Richard Clayton

これは命の恩人です、ありがとう。ECSクラスター内のコンテナー間の通信を処理する方法を理解するのに問題がありました。
ブレナン2016

:(Ubuntuのに基づいて)のPhusionのbasimageで、私はあなたのコマンドを少し変更しなければならなかったifconfig eth0 | grep -oP 'inet \K\S+'
Meuoi

25

唯一の方法は、コンテナーを作成するときにホスト情報を環境として渡すことです

run --env <key>=<value>

19
より具体的には、次のようなコマンドラインオプションを使用して、ブリッジのIPアドレスを渡すことができます-e "DOCKER_HOST=$(ip -4 addr show docker0 | grep -Po 'inet \K[\d.]+')"unix.stackexchange.com/questions/87468/…から受け入れられた回答を使用
ncoghlan

7
Docker for Mac / Windowsでは動作しないと思います。(ブリッジIP)
zx1986

22

これ--add-hostはよりクリーンなソリューションになる可能性があります(ただし、ポート部分がないと、このソリューションで処理できるのはホストだけです)。したがって、docker runコマンドでは、次のようにします。

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print  $3}'` [my container]

https://stackoverflow.com/a/26864854/127400から)


他の誰かが/ etc / hostsにエントリを望んだとき、私は「これのために作られた」と言った。この質問では、それは本当ではありません。また、OPは「ホストとポートマップ」を要求し、ホストのみをカバーしました。
ブライアン

OK。受け入れられた解決策はホスト部分もカバーするだけなので、少し混乱しました。そして私はあなたの解決策が棘の解決策より優れていると思います。
Augunrik、2015年

dind-docker-in-dockerを使用する場合、これは機能しません。内部の港湾労働者は別のIPを持つでしょう
騒々しい

12

これを自動的に実行しようとするほとんどのアプリの標準的なベストプラクティスは次のとおりです。代わりに、コンテナーを実行している人に、外部ホスト名/ IPアドレスを構成として、たとえば環境変数や構成ファイルとして挿入してもらいます。ユーザーがこれを注入できるようにすることで、最もポータブルなデザインが得られます。

なぜこれがそんなに難しいのでしょうか?コンテナは設計上、アプリケーションをホスト環境から分離するためです。デフォルトでは、ネットワークの名前空間はそのコンテナに限定され、ホストの詳細は、完全に信頼されていない可能性のあるコンテナ内で実行されているプロセスから保護されます。


特定の状況に応じて、さまざまなオプションがあります。

コンテナがホストネットワークで実行されている場合は、ホストのルーティングテーブルを直接見て、デフォルトルートアウトを確認できます。この質問から、次のように私のために働きます:

ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'

コンテナ内のホストネットワークでこれを示す例は次のようになります。

docker run --rm --net host busybox /bin/sh -c \
  "ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"

Dockerデスクトップの一部のバージョンでは、組み込みVMにDNSエントリを挿入しました。

getent hosts host.docker.internal | awk '{print $1}'

クラウド環境で実行している場合は、クラウドプロバイダー(AWSなど)からメタデータサービスを確認できます。

curl http://169.254.169.254/latest/meta-data/local-ipv4

外部/インターネットアドレスが必要な場合は、次のようなリモートサービスをクエリできます。

curl ifconfig.co

これらにはそれぞれ制限があり、特定のシナリオでのみ機能します。最も移植性の高いオプションは、構成として注入されたIPアドレスを使用してコンテナーを実行することです。たとえば、次のオプションipは、ホストで以前のコマンドを実行し、環境変数として注入します。

export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP

本当に役立つcurl ifconfig.coコマンド..おかげで:)
MadAboutProgramming

8

IP(ブリッジではなくIP)実際のアドレスWindowsが必要で、Docker 18.03(またはより最近)がある場合は、次のようにします。

イメージ名のあるホストからコンテナでbashを実行しますnginx(動作するAlpine Linux distribution):

 docker run -it nginx /bin/ash

次に、コンテナ内で実行します

/ # nslookup host.docker.internal

Name:      host.docker.internal
Address 1: 192.168.65.2

192.168.65.2ホストのIPです- spinus受け入れられた回答のようなブリッジIPではありません。

私はここでhost.docker.internalを使用しています

ホストのIPアドレスが変化している(ネットワークにアクセスできない場合は変化しない)。18.03以降は、ホストが使用する内部IPアドレスに解決される特別なDNS名host.docker.internalに接続することをお勧めします。これは開発用であり、Docker for Windows以外の実稼働環境では機能しません。


2
私はあなたに解決策を試してみましたが、nslookupコマンドが見つからないようです
Sergey

@Sergeyあなたの画像は基づいていAlpine Linuxますか?そうでない場合は、特定の同等のものを確認してくださいlinux distribution
Kamil Witkowski、2018

いいえ、正確にコマンドを使用します-docker run -it nginx / bin / ash
Sergey

わかりました-Windowsを使用している場合、切り替えてlinux containers使用していませんwindows containers。これを行うには、を右クリックしてdocker iconを選択しSwitch to Linux containersます。画像をダウンロードする際に重要になると思います。windows container古いnginxイメージを削除して再度ダウンロードするかどうかを確認していた場合は、別のコンテナを取得できます。それでも動作しない場合nslookupは、にインストールしてみてくださいash
カミルWitkowski

nslookupを実行できない場合は、pingを実行してください。解決されたIPが表示されます。私にとってこの答えは機能し、host.docker.internalコンテナ内からこのホスト名()を使用しているだけです
Dmitry Minkovsky

7

MacおよびWindows用のTLDR

docker run -it --rm alpine nslookup host.docker.internal

...ホストのIPアドレスを出力します...

nslookup: can't resolve '(null)': Name does not resolve

Name:      host.docker.internal
Address 1: 192.168.65.2

細部

上のマックWindowsの、あなたは特別なDNS名を使用することができますhost.docker.internal

ホストのIPアドレスが変化している(ネットワークにアクセスできない場合は変化しない)。18.03以降は、ホストが使用する内部IPアドレスに解決される特別なDNS名host.docker.internalに接続することをお勧めします。これは開発用であり、Docker Desktop for Mac以外の本番環境では機能しません。


1
複数の質問に同じ回答を追加しないでください。十分な評判を得たら、最高の1つに答え、残りを重複としてフラグを立てます。重複していない場合は、質問に合わせて投稿を調整し、削除のフラグを立てます。
Bhargav Rao

6

Docker for Mac コンテナからホスト上のサービスに接続したい

ホストのIPアドレスが変化している(ネットワークにアクセスできない場合は変化しない)。18.03以降は、ホストが使用する内部IPアドレスに解決される特別なDNS名host.docker.internalに接続することをお勧めします。

ゲートウェイは、gateway.docker.internalとしても到達可能です。 https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds


5

ドッカーのリモートAPIを(たとえば経由で)有効にし、ホストマシンのホスト名またはIPアドレスがわかっている場合、これは多くのbashで実行できます。-Htcp://0.0.0.0:4243

私のコンテナのユーザー内bashrc

export hostIP=$(ip r | awk '/default/{print $3}')
export containerID=$(awk -F/ '/docker/{print $NF;exit;}' /proc/self/cgroup)
export proxyPort=$(
  curl -s http://$hostIP:4243/containers/$containerID/json |
  node -pe 'JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).NetworkSettings.Ports["DESIRED_PORT/tcp"][0].HostPort'
)

2行目は、ローカル/proc/self/cgroupファイルからコンテナーIDを取得します。

3行目は、ホストマシンに向かって丸くなっており(Dockerのポートとして4243を使用している場合)、nodeを使用して、返されたJSONを解析しますDESIRED_PORT


これは、ポート転送を使用する場合にのみ適用されます。実際、HostPortここで有用な情報をすることができ、残念なことにHostIpかもしれない0.0.0.0
Arnout Engelen

4

Ubuntu 16.03を使用しています。私のために

docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print  $3}'` [image]

動作しません(間違ったIPが生成されていました)

私の実用的な解決策はそれでした:

docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]

3

AWSでDockerを実行している場合の別のオプションを次に示します。このオプションを使用すると、apkを使用してcurlパッケージを追加する必要がなくなり、貴重な7MBのスペースを節約できます。組み込みのwget(モノリシックBusyBoxバイナリの一部)を使用します。

wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4

3

AFAIK、Docker for Linux(標準ディストリビューション)の場合、ホストのIPアドレスは常にになります 172.17.0.1

それを取得する最も簡単な方法はifconfig、ホストから(インターフェイスdocker0)を経由することです。

ifconfig

Docker内から、Dockerからの次のコマンド: ip -4 route show default | cut -d" " -f3

次のコマンドラインを使用して、Dockerですばやく実行できます。

# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package   (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:19.10 bash -c "apt-get update && apt-get install iproute2 -y && ip -4 route show default | cut -d' ' -f3"

お役に立てば幸いです。


2

Linuxでは実行できます

HOST_IP=`hostname -I | awk '{print $1}'`

macOSでは、ホストマシンはDockerホストではありません。DockerはそのホストOSをVirtualBoxにインストールします。

HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`

1
最初のコードブロックは、ホストIPではなくコンテナIPを取得します
Ari

mandoc of hostname -Iは、「出力の順序についていかなる仮定もしない」よう警告します。
cannot_mutably_borrow

1

これは、前述のEC2メタデータインスタンスを使用してAWS EC2インスタンスでホストを実行しているユーザー向けの、Node.jsの最小限の実装です

const cp = require('child_process');
const ec2 = function (callback) {
    const URL = 'http://169.254.169.254/latest/meta-data/local-ipv4';
    // we make it silent and timeout to 1 sec
    const args = [URL, '-s', '--max-time', '1'];
    const opts = {};
    cp.execFile('curl', args, opts, (error, stdout) => {
        if (error) return callback(new Error('ec2 ip error'));
        else return callback(null, stdout);
    })
        .on('error', (error) => callback(new Error('ec2 ip error')));
}//ec2

として使用

ec2(function(err, ip) {
        if(err) console.log(err)
        else console.log(ip);
    })


0

これが私のやり方です。この場合、ローカルマシンのIPを指すtaurus-hostを指すdockerイメージ内の/ etc / hostsにhostsエントリを追加します。

TAURUS_HOST=`ipconfig getifaddr en0`
docker run -it --rm -e MY_ENVIRONMENT='local' --add-host "taurus-host:${TAURUS_HOST}" ...

次に、Dockerコンテナー内から、スクリプトはホスト名taurus-hostを使用して、Dockerコンテナーをホストしているローカルマシンにアクセスできます。



0

私が使用するソリューションは、httpリクエストを受け取ったときにDockerホストの外部アドレスを返す「サーバー」に基づいています。

「サーバー」:

1)jwilder / nginx-proxyを起動します

# docker run -d -p <external server port>:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy

2)ipifyコンテナーを起動します

# docker run -e VIRTUAL_HOST=<external server name/address> --detach --name ipify osixia/ipify-api:0.1.0

コンテナがサーバーにhttpリクエストを送信すると、例えば

# curl http://<external server name/address>:<external server port>

DockerホストのIPアドレスは、httpヘッダー「X-Forwarded-For」を介してipifyによって返されます。

例(ipifyサーバーの名前は「ipify.example.com」で、ポート80で実行され、DockerホストのIPは10.20.30.40です):

# docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
# docker run -e VIRTUAL_HOST=ipify.example.com --detach --name ipify osixia/ipify-api:0.1.0

コンテナ内で次のように呼び出すことができます:

# curl http://ipify.example.com
10.20.30.40


-2

Ubuntuでは、hostnameコマンドは次のオプションで使用できます。

  • -i--ip-address ホスト名のアドレス
  • -I--all-ip-addressesホストのすべてのアドレス

例えば:

$ hostname -i
172.17.0.2

変数に割り当てるには、次のワンライナーを使用できます。

IP=$(hostname -i)

これにより、ホストではなくDockerコンテナのIPアドレスが提供されます
Mario Camou

-7

https://docs.docker.com/machine/install-machine/

a)$ docker-machine ip

b)1つ以上のマシンのIPアドレスを取得します。

  $ docker-machine ip host_name

  $ docker-machine ip host_name1 host_name2

10
この取り出しドッキングウィンドウコンテナ、コンテナはホストのIP実行しないことを実行する仮想マシンのIP。
スペンサー・ウィリアムズ

2
これはdocker-machineで実行されているdockerにのみ適用されます。Mac用の新しいdockerはdocker-machineでは実行できません。
thomas.han 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.