VPSにdockerで複数サイトをホスティングするには?VPSにdockerで複数サイトをホスティングするには?suin2017年1月3日複数サイトをひとつのVPSでホスティングする場合、nginxなどのリバースプロキシをフロントに置き、リクエストをバックエンドのウェブサービスに振り分ける構成になります。Dockerを使わなくてもこのような配置になりますが、Dockerで実現する場合はどうしたら良いでしょうか?Dockerでもこのトポロジーと同じようになりますが、本稿では具体的に、リバースプロキシコンテナのnginx-proxyとdocker-composeを使った、比較的管理が容易と思われる方法を紹介します。ひとつのウェブサービスはひとつのdocker-composeにする方針として、ウェブサービスの単位でdocker-compose.ymlを作るようにします。ひとつのdocker-compose.ymlに押し込む方法も考えられますが、そうしません。理由はウェブサービスを開設・閉鎖するたびにdocker-compose.ymlを変更しなければならず、変更ミスがサーバ全体に及ぶ危険性があるためと、サービス名の重複を気にしないとならないためです。ウェブサービスごとにdocker-compose.ymlを作るようにしておけば、影響範囲をウェブサービスひとつに限定できます。ウェブサービスを追加するときも、新たにdocker-compose.ymlを追加するだけで良いので管理も単純です。この方針をディレクトリ構成で表現する場合、僕は次のようにしています。app2が各ウェブサービスのディレクトリで、ウェブサービスを追加するときは、このディレクトリを増やしていきます。sharedはウェブサービスをまたいで利用するサービスを管理します。nginx-proxyのようなリバースプロキシなどがここで管理されます。docker-compose.yml入口となるnginx-proxyの設定フロントに立てるリバースプロキシの設定をdocker-compose.ymlに起こすと次のようになります。proxyはコンテナ名の設定です。省くとdocker-composeが成り行きでshared_proxy_1といった名前をつけます。この設定は好みの問題です。サーバ全体で1つしか起動したくないので、コンテナ名をユニークにしたいというのが設定する動機ではあります。portsの部分はHTTPとHTTPSをリバースプロキシで受け止める設定です。nginx-proxyはSSL証明書を/etc/nginx/certsに配置するとHTTPSも使えるようになるので、443でもリッスンするようにします。volumesの/var/run/docker.sock:/tmp/docker.sockはnginx-proxyがDockerコンテナの起動・終了を検知するために必要です。起動を検知すると、nginxの/etc/nginx/conf.d/default.confを書き換えてupstreamを自動追加してくれます。./certs:/etc/nginx/certsのマウントはSSL証明書置き場です。alwaysは万が一にもnginx-proxyが異常終了してもコンテナを自動再起動する設定です。loggingの部分はログローテーションのための設定で、5MBごとにログファイルを分割し、10ファイルまで残す設定です。networksは、後述しますが、「shared」というブリッジネットワークにリバースプロキシを接続する設定です。docker-composeのv1書式ではdocker-composeをまたいでも同じネットワークに所属できたので、この設定は不要でした。v2書式からはdocker-compose.ymlごとに独立したネットワークが作られるようになったため、サービスをまたいで通信をする場合はどのネットワークに接続するかを明示的にする必要があります。共有ネットワークを作るリバースプロキシと各ウェブサービスが通信できるように、共有ネットワークを作ります。新たにdocker-compose.ymlを作成し、ウェブサービスの設定をします。ここではWordPressを例にします。shared環境変数VIRTUAL_HOSTは、nginx-proxyのための設定です。ここで宣言したホスト名でnginx-proxyが自動的にアクセスをこのサービスに振り分けてくれます。ここでもウェブサービスを共有ネットワークに乗せるために、networksの設定が必要になります。これがないとnginx-proxyからの通信が行えなくなります。ここまでの設定でトポロジーはこんな感じになります。各サービスを起動するリバースプロキシを起動します。-dウェブサービスを起動します。-dデータベースを共有のコンテナにする先述のウェブサービスのdocker-compose.ymlではMySQLのコンテナはそのウェブサービスが専有するものにしていました。この方法はシンプルで、ウェブサービスごとにデータベースの設定ができたりと柔軟です。一方で、ウェブサービスが沢山できてくるとデータのバックアップが面倒だったり、SequelProなどのクライアントでつなぐために、ウェブサービスごとにMySQLのポート番号を決めなければならなかったりと、運用面が不便さがあります。どちらもトレードオフだと思いますが、ひとつのVPSにMySQLをひとつだけ起動する方法についても触れておきます。データベースを共有のコンテナにした際のトポロジーはこんな感じです。shared/docker-compose.ymlのservicesにmysqlを追加します。sharedmysqlはポート3306を開けておきます。これは、SequelProなどのMySQLクライアントで入れるようにするためのものです。DBをメンテするときにポートが空いていると、SSH越しにアクセスできるので便利です。次にウェブアプリ側のdocker-compose.ymlからmysqlを取り除いて、代わりにexternal_linksで共有のmysqlコンテナにつながるようにします。sharedこれでサーバひとつにつきMySQLがひとつにできます。おわりVPSで複数サイトをdockerで実現する方法を紹介しました。本稿で作成したdocker-composeのファイルはGitHubで公開しています。2.6suintwitter2017年1月3日ひとつのウェブサービスはひとつのdocker-composeにする入口となるnginx-proxyの設定共有ネットワークを作るウェブサービスの設定各サービスを起動するデータベースを共有のコンテナにするおわり。