
ヘッダー
/etc/hosts
コンテナ内にDockerホストの正しいIPアドレスを追加する一般的なシェルスクリプトを作成したいと思います。
私はアクセスしたいサービスを他のDockerコンテナに入れることを提案するかもしれませんが、最速のCIテストのためにコンテナのIPを介してDockerホストにアクセスしたいので、それが必要です。
一つあるgithubの問題には多くのコメントがあります人々はホストIPにアクセスするための統合された方法を必要としています。すべてのプラットフォームATMに適用できる単一のソリューションはありません。
人々は次のようなスクリプトを作成します。
grep dockerhost /etc/hosts || echo $(ip r | grep ^default | cut -d" " -f3) dockerhost >> /etc/hosts
Dockerホストにアクセスするために同じ方法を使用したいのですが、Mac atmでは機能しません。返される結果は次のとおりです。
ip r | grep ^default | cut -d" " -f3
DockerホストがMacの場合、誤った答えが表示されます172.17.0.1
(実際にはコンテナを使用してコンテナからMacにアクセスできません172.17.0.1
)。
Mac用Dockerには、次の機能があります。特殊ホスト名 docker.for.mac.localhost
これを使用して、コンテナからホストMacにアクセスできます。
質問
まず、確認されたアドレスをsh
解析して 。docker.for.mac.localhost
/etc/hosts
ip r | grep ^default | cut -d" " -f3
/etc/hosts
docker.for.mac.localhost
質問は:どのコンテナでもどのように解析しようとしますか? (nslookup
たとえば、一部のディストリビューションではありません)。それとも、問題を解決しようとせずdocker.for.mac.localhost
にどこかで値を読み取ろうとしますか?
私の現在の考えは、試してみて、getent ahosts docker.for.mac.localhost
コマンドが存在しない場合はそれを試してみることです(つまり、Busyboxイメージにコマンドがnslookup
ありません)。getent
たぶん私は間違って解決しようとしているかもしれませdocker.for.mac.localhost
んし、より簡単な方法で検索することができます。あなたの考えを共有してください。
ありがとうございます。
答え1
docker.for.mac.localhostを解決するアイデアは明らかです。ほとんどすべてのコンテナでこれを解決できるものを見つけることができます。これを行うことができます(私のテストによると)。
grep dockerhost /etc/hosts || echo $( (ping -c1 docker.for.mac.localhost || (ip r | grep ^default)) | grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts
エントリポイント()の一部として実行することも、ある種の初期sh -c
化スクリプトで実行することもできます。
詳しくは、より完全なバージョンのレビューと注意事項については、読んでください。
私たちがすることは、Linuxに名前を付けさせるだけです。 ncとTracerouteはほぼどこにでも存在しますが、Pingは最も単純なオプションです。他のすべての方法が失敗した場合は、実際に最新の(BusyBoxではない)bashまたはsyslogを使用してこれを実行できます。既定では、Dockerは同じネットワーク上の他のコンテナ(または以前のバージョンではリンクされたコンテナ)の名前に応答する小さなDNSサーバーを設定します。その後、docker.for.mac.localhost
追加します。
解決できない場合は、DNSサーバーが解決できなかったので、正常にホストを取得できるという意味です。代わりに/proc/netメソッドを使用することもできますが、私のテストコンテナでは同じように見えます。
今、いくつかの注意点があります。まず、大きな問題です。ネットワークに接続していない場合は、最大30秒までの時間が永久に超過します。以下の大きなスクリプトにはいくつかの修正があります。また、コンテナのビルドプロセス中にそれを実行することはできません(デフォルトではそれをオーバーライドする方法があります)。代わりに何もしないかもしれません。 Dockerはコンテナを起動すると新しい/ etc / hostsをマウントします。
より良いバージョンが動作しますtimeout
が、問題があります。互換性のないバージョンが(少なくとも)2つあり、存在しない可能性があると仮定したい場合は、3番目のケースがあります。
grep dockerhost /etc/hosts || echo $( (
(if timeout -t1 env >/dev/null; then \
timeout -t1 ping -c1 docker.for.mac.localhost; \
elif timeout 1s env >/dev/null; then
timeout 1s ping -c1 docker.for.mac.localhost; \
else \
ping -c1 docker.for.mac.localhost; \
fi) \
|| (ip r | grep ^default)) \
| grep -oE '([0-9]+\.){3}[0-9]+' ) dockerhost >> /etc/hosts
envを使用する理由は、組み込まれていないシェルバージョン(ほとんど/usr/bin/env
の場合)がほとんど確実で、よく知られているインターフェース(つまり入力なしで実行されます)があり、次の影響を受ける可能性がほとんどないためです。環境ls
ファイルシステムに依存する不快なコマンドとは異なる理由で失敗する問題。
最後に、私が使用しているものと同様の完全に注釈付きのバージョンです(私の後ろの人々が何が起こっているのか理解できるように):
add_dockerhost_address() {
# The name we're checking for - in case this technique is useful on Windows
# if we get a Windows version instead of a cross-platform one
local MACHOST="docker.for.mac.localhost"
# The name we want to insert into /etc/hosts
local DOCKERHOSTNAME="dockerhost"
# Don't insert the name twice
if grep "$DOCKERHOSTNAME" /etc/hosts >/dev/null 2>&1; then
return 0
fi
# A command string we'll be building
local COMMAND=""
# Check for the ability to limit the timeout
if command -v timeout >/dev/null 2>&1; then
# We still have a problem - there are two widely used incompatible
# variants of timeout. Let's see which one we have.
# env should not be a builtin, doesn't require a pipe,
# has a consistent command line test, and is unlikely to fail
if timeout -t1 env >/dev/null 2>&1; then
COMMAND="timeout -t1 "
else
COMMAND="timeout 1s "
fi
fi
local IS_NOT_MAC=1
local IP=""
if command -v ping >/dev/null 2>&1; then
COMMAND="$COMMAND ping -c1 $MACHOST"
# Otherwise, BusyBox shows terminated.
IP=$(sh -c "$COMMAND" 2>&1)
# Exit codes: 0 - found the host, 1/2 failed to find, 124/143 terminated
IS_NOT_MAC="$?"
fi
if [ "$IS_NOT_MAC" -eq 0 ]; then
IP=$(echo "$IP" | grep -oE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}')
else
IP=$(ip r | grep ^default | cut -d" " -f3)
fi
echo "$IP $DOCKERHOSTNAME" >> /etc/hosts
}
add_dockerhost_address
exec "/usr/sbin/apachectl" "-DFOREGROUND"
答え2
私はそれが言及されたと信じていますここ使用できますdocker.for.mac.host.internal
。言及されていませんが、docker.for.mac.localhost
私にも効果があります。
次に、次の行を使用してDocker for Macで実行されていることを確認します。
$ getent hosts docker.for.mac.host.internal
$?
docker.for.mac.host.internal
見つかったら教えてください。
実際のIPを取得するには、awk
以下を使用することもできます。
$ getent hosts docker.for.mac.host.internal | awk '{ print $1 }'