Dockerポートへのvhostの割り当て


83

カスタムドメイン(* .foo)へのすべてのWebリクエストがDockerホストのIPアドレスにマップされるように、ワイルドカードDNSを設定しています。Apache(またはNginx)インスタンスを実行している複数のコンテナーがある場合、各コンテナーはApacheポート(80)をいくつかの外部インバウンドポートにマップします。

私がやりたいのは、カスタムDNSサーバーを介して(Dockerホストの)正しいIPアドレスに既にマップされているcontainer-1.fooにリクエストを送信することですが、デフォルトのポート80リクエストを正しいDocker外部にプロキシします指定されたコンテナからの正しいApacheインスタンスがカスタムドメインに基づいて応答できるようにポートします。同様に、container-2.fooは2番目のコンテナのapacheにプロキシします。

これに対する事前に構築されたソリューションはありますか、DockerホストでNginxプロキシを実行するのが最善の策ですか、それともDockerコンテナを管理する可能性のあるnode.jsプロキシを作成する必要があります(Web経由で開始/停止/再構築) )、または...?Dockerコンテナーをより自然なイベントのように使用し、無関係なポートやコンテナーのジャグリングを使用しないようにするためのオプションはありますか?


私にもこの質問があります-私が知る限り、Dockerコンテナーで各アプリを実行してから、nginxサーバー(おそらくそれ自体のコンテナー)を使用してホストでルーティングを実行するのがその方法です。アプリサーバーをスタンドアロンで実行する(つまり、php-fpm、pumaなどのサーバーを公開する)か、(無意味な?)nginxインスタンスも含める必要があるのか​​疑問に思っています。
ロス

github.com/dotcloud/hipacheを見てください。これは、redisを介して構成可能なリバースプロキシです。
ZeissS 2013

回答:


81

この答えは少し遅れるかもしれませんが、必要なのは自動リバースプロキシです。そのために2つのソリューションを使用しました。

  • jwilder / nginx-proxy
  • Traefik

時間が経つにつれて、私の好みはTraefikを使用することです。主な理由は、十分に文書化および保守されており、より多くの機能(さまざまな戦略と優先順位による負荷分散、ヘルスチェック、サーキットブレーカー、ACME / Let's Encryptによる自動SSL証明書など)が付属しているためです。


jwilder / nginx-proxyの使用

DockerコンテナーJasonWilderのnginx-proxyDockerイメージを実行すると、他のコンテナーのリバースプロキシとしてnginxサーバーがセットアップされ、構成を維持する必要がありません。

VIRTUAL_HOST環境変数を使用して他のコンテナーを実行するだけで、nginx-proxyがそれらのip:portを検出し、nginx構成を更新します。

*.test.localDockerホストのIPアドレスにマップするようにDNSが設定されているとしましょう。次に、次のコンテナーを起動して、簡単なデモを実行します。

# start the reverse proxy
docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock jwilder/nginx-proxy

# start a first container for http://tutum.test.local
docker run -d -e "VIRTUAL_HOST=tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -e "VIRTUAL_HOST=deis.test.local" deis/helloworld

Traefikの使用

Traefikコンテナを実行すると、リバースプロキシサーバーがセットアップされ、コンテナにあるDockerラベルを指定して転送ルールが再構成されます。

*.test.localDockerホストのIPアドレスにマップするようにDNSが設定されているとしましょう。次に、次のコンテナーを起動して、簡単なデモを実行します。

# start the reverse proxy
docker run --rm -it -p 80:80 -v /var/run/docker.sock:/var/run/docker.sock traefik:1.7 --docker

# start a first container for http://tutum.test.local
docker run -d -l "traefik.frontend.rule=Host:tutum.test.local" tutum/hello-world

# start a second container for http://deis.test.local
docker run -d -l "traefik.frontend.rule=Host:deis.test.local" deis/helloworld

-v /var/run/docker.sock:/tmp/docker.sockそれは危険な解決策ですか?このnginxプロキシがDockerホストデーモンにアクセスできるコンテナ?これはセキュリティホールの可能性がありますか?
Mikl

おそらく。また、共有しないこと/var/run/docker.sockは、Dockerホストがコンテナーから悪用されないことを保証するものでもないことに注意してください。Dockerのセキュリティはそれ自体が主題です。
Thomasleveil 2014年

既知のセキュリティ問題はありますか?コンテナからDockerホストに到達できる場合。
mikl 2014年

過去にエクスプロイトが存在し、問題は修正されましたが、将来、新しいエクスプロイトが見つかる可能性があります。Dockerはセキュリティを追加することではなく、展開の容易さについてです
Thomasleveil 2014年

5
また、nginx-proxyとdocker-genを別々に実行して、dockerソケットがnginxコンテナーにマウントされないようにすることもできます。
ジェイソンワイルダー2014

42

考えられる答えは次の2つです。(1)Dockerで直接ポートをセットアップし、Nginx / Apacheを使用してvhostをプロキシするか、(2)Dokkuを使用してポートとvhostを管理します(これが方法1の方法です)。

方法1a(dockerでポートを直接割り当てる)

ステップ1:ホストにnginx.confまたはApacheをセットアップし、必要なポート番号を割り当てます。ホスト上で実行されているこのWebサーバーは、仮想ホストのプロキシを実行します。Dockerに関してこれについて特別なことは何もありません-それは通常の仮想ホストホスティングです。次に、ステップ2で、Dockerに正しいホストポート番号を使用させるための特別な部分があります。

手順2:次のように、「-p」を使用してDockerのポート番号を強制的に割り当て、Dockerのポートマッピングを設定し、「-e」を使用してDocker内のカスタム環境変数を設定します。

port=12345 # <-- the vhost port setting used in nginx/apache
IMAGE=myapps/container-1
id=$(docker run -d -p :$port -e PORT=$port $IMAGE)
# -p :$port will establish a mapping of 12345->12345 from outside docker to
# inside of docker.
# Then, the application must observe the PORT environment variable
# to launch itself on that port; This is set by -e PORT=$port.

# Additional goodies:
echo $id # <-- the running id of your container
echo $id > /app/files/CONTAINER # <-- remember Docker id for this instance
docker ps # <-- check that the app is running
docker logs $id # <-- look at the output of the running instance
docker kill $id # <-- to kill the app

方法1bハードコードされたアプリケーションポート

...アプリケーションがハードコードされたポート、たとえばポート5000を使用している場合(つまり、方法1aのようにPORT環境変数を介して構成できない場合)、次のようにDockerを介してハードコードできます。

publicPort=12345
id=$(docker run -d -p $publicPort:5000 $IMAGE)
# -p $publicPort:5000 will map port 12345 outside of Docker to port 5000 inside
# of Docker. Therefore, nginx/apache must be configured to vhost proxy to 12345,
# and the application within Docker must be listening on 5000.

方法2(Dokkuにポートを把握させる)

現時点では、Dockervhostを管理するためのかなり良いオプションはDokkuです。今後のオプションはFlynnを使用することかもしれませんが、現時点では、Flynnはまだ始まったばかりで、準備が整っていません。したがって、今はDokkuを使用します。Dokkuのインストール手順に従った後、単一ドメインに対して、「VHOST」ファイルを作成して仮想ホストを有効にします。

echo yourdomain.com > /home/git/VHOST
# in your case: echo foo > /home/git/VHOST

これで、アプリがSSH経由でDokkuにプッシュされると(これを行う方法についてはDokkuのドキュメントを参照)、DokkuはVHOSTファイルを確認し、プッシュされた特定のアプリ(たとえば、「container-1」をプッシュした場合)を生成します。次のファイル:

/home/git/container-1/nginx.conf

また、次の内容になります。

upstream container-1 { server 127.0.0.1:49162; }
server {
  listen      80;
  server_name container-1.yourdomain.com;
  location    / {
    proxy_pass  http://container-1;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $remote_addr;
  }
}

サーバーが再起動されると、Dokkuは、Dockerがランダムに別のポートを割り当てられるのではなく、最初にデプロイされたポート(ここでは49162)にマップされたポートでアプリケーションを起動するようにします。この決定論的な割り当てを実現するために、Dokkuは最初に割り当てられたポートを保存/home/git/container-1/PORTし、次回の起動時にPORT環境をこの値に設定し、Dockerのポート割り当てをホスト側とアプリ側の両方でこのポートにマップします。これは、Dokkuが設定PORT=5000し、VPS側でDokkuがアプリ側で5000にマップするランダムポートを特定する最初の起動とは対照的です。ラウンドアバウトですが(将来変更される可能性もあります)、機能します。

内部でのVHOSTの動作方法は、SSH経由でアプリのgitプッシュを実行すると、Dokkuはにあるフックを実行し/var/lib/dokku/plugins/nginx-vhostsます。これらのフックもここのDokkuソースコードありnginx.conf、正しい仮想ホスト設定でファイルを書き込む役割を果たします。の下/var/lib/dokkuにこのディレクトリがない場合は、を実行してみてくださいdokku plugins-install


3

dockerを使用すると、内部IPを通常(80など)のままにして、ランダムポートを接続する方法を理解する必要があります。

それらを処理する1つの方法は、hipacheのようなリバースプロキシを使用することです。DNSをその場所に向けると、コンテナが上下するときにプロキシを再構成できます。見てみましょうhttp://txt.fliglio.com/2013/09/protyping-web-stuff-with-docker/これは仕事ができるかを確認します。

より堅牢なものをお探しの場合は、「サービス検出」をご覧ください。(dockerを使用したサービスディスカバリの概要:http//txt.fliglio.com/2013/12/service-discovery-with-docker-docker-links-and-beyond/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.