タイトルが言うように。 dockerホストのIPアドレスとホストからコンテナへのポートマップを取得し、それをコンテナ内で実行できるようにする必要があります。
/sbin/ip route|awk '/default/ { print $3 }'
@MichaelNealeが気づいたように、このIPはビルド時にハードコーディングされるので、Dockerfile
でこのメソッドを使う意味はありません。
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
更新: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があなた自身のネットワーク上の何かと衝突しないことを確認してください。
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
唯一の方法は、コンテナーを作成するときにホスト情報を環境として渡すことです。
run --env <key>=<value>
--add-Host
はもっときれいな解決策になるかもしれません(しかしport部分がなければ、Hostだけがこの解決策で扱えます)。それで、あなたの docker run
コマンドで、以下のようにしてください:
docker run --add-Host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [my container]
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
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以外の運用環境では機能しません。
dockerリモートAPI を(例えば -H
tcp://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
を解析します。
これは、AWSでDockerを実行している人のための別のオプションです。このオプションは、curkパッケージを追加するためにapkを使用することを避け、貴重な7MBのスペースを節約します。組み込みのwget(モノリシックBusyBoxバイナリの一部)を使用してください。
wget -q -O - http://169.254.169.254/latest/meta-data/local-ipv4
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'/.$//'`
自動的にこれを実行しようとしているほとんどのアプリにとって標準的なベストプラクティスは、そうではありません。代わりに、コンテナを実行している人に設定として外部のホスト名/ 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
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]
これは、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);
})
これが私のやり方です。この場合、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コンテナーをホストしている私のローカルマシンにアクセスできます。
私が使用する解決策は、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
たぶん私が作成したコンテナも便利です https://github.com/qoomon/docker-Host
ホスト名にアクセスするには、単にコンテナ名dnsを使用できます。 curl http:// dockerhost:9200 なので、どんなIPアドレスでも面倒なことは必要ありません。
Service Fabricクラスター上でWindowsコンテナーを実行している場合は、ホストのIPアドレスは環境変数Fabric_NodeIPOrFQDN
から入手できます。 Service Fabricの環境変数
Ubuntuでは、hostname
コマンドは以下のオプションで使用できます。
-i
、--ip-address
アドレス-I
、--all-ip-addresses
すべてのホストのアドレス例えば:
$ hostname -i
172.17.0.2
変数に代入するには、次のようなワンライナーを使うことができます。
IP=$(hostname -i)