web-dev-qa-db-ja.com

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

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

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

@MichaelNealeが気づいたように、このIPはビルド時にハードコーディングされるので、Dockerfileでこのメソッドを使う意味はありません。

269
spinus

Docker for Mac 、バージョン18.03以降、ホストのIPアドレスとしてHost.docker.internalを使用できます。

ドキュメンテーション にあるように、これは開発目的のためであり、Docker for Mac以外の実稼働環境では機能しません。これは、Docker for Macでは、「ホスト上にdocker0インターフェイスが表示されないためです。このインターフェイスは実際には仮想マシン内にあります」。

これは、バージョン17.06以降で利用可能なdocker.for.mac.localhost、およびバージョン17.12以降で利用可能なdocker.for.mac.Host.internalからのアップデートですが、これらも機能する可能性があります。

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

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
119
allanberry

更新:On Docker for Mac 、バージョン18.03以降、ホストのIPアドレスとして Host.docker.internal を使用できます。 allanberryの答え を参照してください。 Mac用のDockerの以前のバージョンでは、次の答えがまだ役に立つかもしれません:

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

ipconfig getifaddr en0

これにより、現在のネットワーク上のMacのIPが表示され、docker containerもこのアドレスに接続できるはずです。このIPアドレスが変わってしまった場合、これはもちろん苦痛ですが、あなたがあなたのMacにカスタムループバックIPを追加することができます。

Sudo ifconfig lo0 alias 192.168.46.49

Telnetを使ってdocker container内から接続をテストすることができます。私の場合は、リモートの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/8を示していました。これは127.*の範囲のIPを使用できなかったことを意味します。そのため、上記の例で192.168.*を使用しました。あなたが使用するIPがあなた自身のネットワーク上の何かと衝突しないことを確認してください。

78
Code Commander

AWSでDockerを実行している場合は、Hostの instance meta-data をコンテナ内から使用できます。

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
39
Nate Fox

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

run --env <key>=<value>
22
Magno Torres

--add-Hostはもっときれいな解決策になるかもしれません(しかしport部分がなければ、Hostだけがこの解決策で扱えます)。それで、あなたの docker run コマンドで、以下のようにしてください:

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

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

19
ma-ver-ick

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

6
BSCheshir

IP上に実際のIPアドレス(ブリッジWindowsではない)が必要で、ドッカー18.03(またはもっと最近のもの)がある場合は、次のようにします。

イメージ名がnginxのホストからコンテナに対してbashを実行します(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以外の運用環境では機能しません。

6
yami

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

私のコンテナのユーザの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行目はHostマシンに向かって曲がり(dockerのポートとして4243を使用していると仮定して)、nodeを使用して返されたJSONのDESIRED_PORTを解析します。

5
PCas

これは、AWSでDockerを実行している人のための別のオプションです。このオプションは、curkパッケージを追加するためにapkを使用することを避け、貴重な7MBのスペースを節約します。組み込みのwget(モノリシックBusyBoxバイナリの一部)を使用してください。

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

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'/.$//'`
2
Aref Aslani

自動的にこれを実行しようとしているほとんどのアプリにとって標準的なベストプラクティスは、そうではありません。代わりに、コンテナを実行している人に設定として外部のホスト名/ IPアドレスを注入させます。環境変数または設定ファイルとして。ユーザーがこれを注入できるようにすると、最も移植性の高いデザインになります。

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


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

コンテナがホストネットワーキングで動作している場合は、ホスト上のルーティングテーブルを直接見てデフォルトのルートアウトを確認できます。

ip r s 0/0 | awk '{print $3}

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

docker run --rm --net Host busybox /bin/sh -c "ip r s 0/0 | awk '{print \$3}'"

Docker Desktopの一部のバージョンでは、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コマンドを実行し、それを環境変数として注入するオプションです。

docker run --rm -e Host_IP=$(ip r s 0/0 | awk '{print $3}') busybox printenv Host_IP
1
BMitch

Ubuntu 16.03があります。私のために

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

NOT work(間違ったipが生成されていた)

私の作業ソリューションは次のとおりでした:

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

これは、Node.jsの最小限の実装であり、誰がAWS EC2インスタンスでホストを実行していますか、前述の EC2メタデータインスタンス を使用して

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);
    })
1
loretoparisi

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

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

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

0
djangofan

私が使用する解決策は、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 Hostの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
0
ramazotto

たぶん私が作成したコンテナも便利です https://github.com/qoomon/docker-Host

ホスト名にアクセスするには、単にコンテナ名dnsを使用できます。 curl http:// dockerhost:9200 なので、どんなIPアドレスでも面倒なことは必要ありません。

0
qoomon

Service Fabricクラスター上でWindowsコンテナーを実行している場合は、ホストのIPアドレスは環境変数Fabric_NodeIPOrFQDNから入手できます。 Service Fabricの環境変数

0
Aaron Marten

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

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

例えば:

$ hostname -i
172.17.0.2

変数に代入するには、次のようなワンライナーを使うことができます。

IP=$(hostname -i)
0
kenorb