ヘッダー

ヘッダー

ヘッダー

/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/hostsip 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"

おすすめ記事