新しいプロジェクトが立ち上がるたびに、都度virtual boxやvagrant、dockerなどを使って開発環境を構築していたのですが、 数が多くなるとリソースや管理が・・・と思い、 一つのvagrant(Virtualbox)内で、複数のプロジェクトの開発環境(docker-compose)を構築できないかと思い作成し、テンプレート化しました。 リバースプロキシを設定することにより、ホスト名でアクセスするdockerコンテナを変更することができます。

まだまだ改良の余地がありそうですが、とりあえず第一弾ということで公開いたします。 色々意見等いただけると嬉しい。

試しに使ってみたいという方は、以下の手順で構築可能かと思います。

GitHubで公開しておりますので、よければお使いください。 https://github.com/hirasaki1985/reverse_proxy

テンプレートの実行

ダウンロード&インストール

環境構築

$ git clone https://github.com/hirasaki1985/reverse_proxy.git
$ cd reverse_proxy
$ vagrant up
$ sudo vi /etc/hosts
  192.168.33.10 web-project01.com
  192.168.33.10 web-project02.com

アクセス

$ access your browser.
  http://web-project01.com
  http://web-project02.com

それぞれのwebプロジェクトの画面が表示されれば成功です。

解説

フォルダ構成

├── Vagrantfile
└── docker-composes
    ├── proxy
    │   ├── Dockerfile
    │   └── docker-compose.yml
    ├── web-project01
    │   ├── docker-compose.yml
    │   ├── html
    │   │   └── index.html
    │   └── php
    │       └── Dockerfile
    └── web-project02
        ├── docker-compose.yml
        └── html
            ├── 50x.html
            └── index.html

docker-composesフォルダ配下に、プロジェクト単位でフォルダを設置します。 proxyフォルダは、リバースプロキシ用のdocker-composeファイルが格納されてます。ここには手を加えなくていいはず。

それぞれのプロジェクト配下にdocker-compose.ymlファイルを作成していき、開発環境構築に必要なファイルの準備や記述をしていきます。

Vagrantfile

  config.vm.network "forwarded_port", guest: 80, host: 80
  config.vm.network "forwarded_port", guest: 443, host: 443
  config.vm.network "private_network", ip: "192.168.33.10"

この設定で、ポート80と443でホストからゲストに疎通できるようにします。 ホストから ping 192.168.33.10 とか、 nc -z 192.168.33.10 80 で疎通確認ができます。

config.vm.synced_folder "./docker-composes", "/docker-composes"

そして、docker-composesフォルダをvagrantで立ち上げたゲストOS内のフォルダと同期をします。 この設定により、ホストOSでファイルを更新すれば、ゲストOSに更新が反映されます。

  ## create docker network
  #sudo docker network create --driver bridge web-project01_network
  #sudo docker network create --driver bridge web-project02_network
  sudo docker network create --driver bridge common_link

この部分で、docker内のネットワークを作成します。 プロジェクト毎にネットワークを分けたかったのですが、リバースプロキシのdockerコンテナを複数のネットワークに所属される方法がわからなかったので、common_linkという一つのネットワーク内に複数のプロジェクトのコンテナイメージを作成してます。

$start = <<SCRIPT
  ## up nginx-proxy
  # sudo docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy
  sudo /usr/local/bin/docker-compose -f /docker-composes/proxy/docker-compose.yml stop 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/proxy/docker-compose.yml rm -f 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/proxy/docker-compose.yml up -d

  ## up web-project01
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project01/docker-compose.yml stop 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project01/docker-compose.yml rm -f 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project01/docker-compose.yml up -d

  ## up web-project02
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project02/docker-compose.yml stop 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project02/docker-compose.yml rm -f 2>&1
  sudo /usr/local/bin/docker-compose -f /docker-composes/web-project02/docker-compose.yml up -d
SCRIPT

再起動する度に上記コマンドが呼び出されます。 リバースプロキシの設定がしてあるnginx-proxyと2つのプロジェクトのdocker-composeファイルを一旦削除した後に実行しています。 もしプロジェクトを追加したい場合は、こちらに新たに行を追加します。 ここら辺、シェルスクリプトなどで自動化できそうですね。

あとは、開発環境に合わせてdocker-composeファイルを作成していきます。 テンプレートだと、 web-project01がapache + php, web-project02がnginxというようにdocker-composeファイルを作成しました。

proxy/docker-compose.yml

version: '2'

services:
  nginx-proxy:
    #image: jwilder/nginx-proxy
    build: ./
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
    restart: always

networks:
  default:
    external:
      name: common_link
  #web01:
  #  external:
  #    name: web-project01_network
  #web02:
  #  external:
  #    name: web-project02_network

ポート80番と443番でリバースプロキシの設定をしています。 SSLも対応できるみたいですが、今回はそこまで行いませんでした。 dockerのネットワークをプロジェクト毎に分けようと思ってできなかった名残りがあります。 コメント部分は消しちゃってください。

余談ですけど、最初はvagrantのイメージはcentosを使っていたのですが、 centosでインストールしたyum install -y dockerではリバースプロキシがうまく動いてくれませんでした。 そのため、ubuntuで構築してます。

web-project01/docker-compose.yml

version: '2'

services:
  web01:
    build: ./php
    container_name: web-project01
    environment:
      - VIRTUAL_HOST=web-project01.com
    volumes:
      - ./html:/var/www/html
    restart: always

networks:
  default:
    external:
      #name: web-project01_network
      name: common_link

ここのキモは、VIRTUAL_HOSTの設定です。 jwilderさんが作成してくださったリバースプロキシは、ここの環境変数を見に行って、自動でリバースプロキシの対象として認識してくれます。すごいの一言です。 jwilderさんのリバースプロキシの使い方は他にたくさんあるので割愛しますが、 同じネットワーク内(ここでいうcommon_link)にリバースプロキシに登録したいコンテナを作成してください。

これにより、 hostsファイルを「192.168.33.10 web-project01.com」と設定して、 ブラウザから「http://web-project01.com」にアクセスすることで、 dockerコンテナの「web-project01」のポート80にアクセスしにいくという流れになります。

web-project01コンテナはphp:7-apacheがベースイメージで、ポート80番はapacheが監視しています。 docker-composeで「./html:/var/www/html」とvolumesの設定をしているので、 ./web-project01/html配下のファイルがweb-project01コンテナ内の「/var/www/html」にマウントされます。

このため、http://web-project01.comにアクセスしたら、./web-project01/html/index.htmlが呼び出されます。

web-project02/docker-compose.yml

version: '2'

services:
  web02:
    image: nginx
    container_name: web-project02
    environment:
      - VIRTUAL_HOST=web-project02.com
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always

networks:
  default:
    external:
      #name: web-project02_network
      name: common_link

こっちはnginxで作成しました。 「VIRTUAL_HOST=web-project02.com」と書くことで、リバースプロキシに自動で追加されます。 あとはweb-project01同様、hostsファイルに登録することで、 web-project02コンテナ内のnginxサーバに「http://web-project02.com」でアクセスすることができます。 上記アクセスだと呼び出されるhtmlファイルは、「./web-project02/html/index.html」になります。

総括

webサーバしか試してませんが、一つのVagrantの環境内に複数のプロジェクトを立ち上げることができました。 今後はこれを応用してwebサーバ+aiサーバなども取り組んでいこうかと思います。

vagrantもdockerも機能が豊富なので、他にもっと楽で効率の良い方法がありそうです。 もしご存知の方は、コメントしてくれるとありがたいです。

こんなのでよければ、ぜひ使ってやってください。

参考

以下のサイトの情報を参考にさせていただきました。 ありがとうございました。