RedmineをElasticBeanstalkのMulti-Container Dockerで起動してみた

ElasticBeanstalkをいろいろ試している最中。
今回はMulti−Container Dockerのお試し。

## 方針

* Redmineのコンテナとリバースプロキシ用のNginxコンテナを使う。
* AWSなのでデータベースはRDSを使う。
* お試しなのでDocker RegistoryはDockerhubを使う。
* RedmineのDockerイメージはお約束の`sameersbn/redmine`

## EBアプリケーションのソースバンドル作成

この時点ではまだAWSを触る必要はない。
ディレクトリとファイルの構成は以下のような感じ。

```
.
├── Dockerrun.aws.json
├── nginx/
│   └── conf.d/
│       └── default.conf
└── redmine/
    └── data/
        └── .gitkeep
```

Dockerrun.aws.jsonにコンテナの構成を記載する。
どうやらECSのTask Definisionと同じような内容のようだ。

```json:Dockerrun.aws.json
{
  "AWSEBDockerrunVersion": 2,
  "volumes": [
    {
      "name": "redmine-data",
      "host": {
        "sourcePath": "/var/app/current/redmine/data"
      }
    },
    {
      "name": "nginx-conf",
      "host": {
        "sourcePath": "/var/app/current/nginx/conf.d"
      }
    }
  ],
  "containerDefinitions": [
    {
      "name": "redmine",
      "image": "sameersbn/redmine",
      "essential": true,
      "memory": 512,
      "mountPoints": [
        {
          "sourceVolume": "redmine-data",
          "containerPath": "/home/redmine/data"
        }
      ],
      "environment": [
        {
          "name": "REDMINE_RELATIVE_URL_ROOT",
          "value": "/redmine"
        },
        {
          "name": "DB_ADAPTER",
          "value": "postgresql"
        }
      ]
    },
    {
      "name": "nginx-proxy",
      "image": "nginx",
      "essential": true,
      "memory": 128,
      "mountPoints": [
        {
          "sourceVolume": "nginx-conf",
          "containerPath": "/etc/nginx/conf.d",
          "readOnly": true
        }
      ],
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 80
        }
      ],
      "links": [
        "redmine:redmine"
      ]
    }
  ]
}
```

ホストの環境変数を自動で引き継いでくれるみたいなのでDB_HOSTやDB_NAMEなどはEBの環境変数で渡せるためここでは書かない。**逆にここに書いちゃうと環境ごとに作らないとなので絶対にやらない。**
logConfigurationでCloudWatch LogsやFluentdが使えるみたいだけど、今回は割愛。

Redmineはサブディレクトリにしてみた。
複数アプリケーションをNginxでパスルーティングできることのフィジビリティ確保。（ALB使えや）
Route53でドメイン名を複数このEBに紐付けてホスト名での振り分けもできそう。
ホスト名でのルーティングはALBでは（今のところ）できない。

```nginx:nginx/conf.d/default.conf
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    location /redmine {
      proxy_set_header X-Real-IP  $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_pass http://redmine;
    }
    error_page  404              /404.html;
    error_page  500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
```

で、ローカルのGitリポジトリにcommitしておく。

```bash
git init && git add ./* && git commit -m "initial commit."
```

## 必要なリソースを事前準備

RDSとセキュリティグループは事前に作成しておかないと最初のデプロイでコケるので事前に作成しておく。

* VPC * 1, Internet Gateway * 1, RouteTable * 1, Subnet * 1
* ElasticBeanstalk用のSecurity Group (80/tcp 0.0.0.0/0) * 1
* PostgreSQLのRDS (EBで作成しない)
  * RDSのSecurityGroupで上で作ったSecurityGroupからのアクセスを許可しておく。

## ElasticBeanstalkの環境を作成する

マネジメントコンソールでもできるけど、ElasticBeanstalkはeb-cliを使ったほうが便利。（というかcliじゃないとできない設定が多すぎる）

```bash
# アプリケーションの作成
eb init --region ap-northeast-1 -p "multi-container-docker-1.12.6-(generic)" test-app
eb create -r ap-northeast-1 -c CNAMEのプレフィクス -i t2.small -k EC2キーペア \
  -p "multi-container-docker-1.12.6-(generic)" --single \
  --envvars "DB_HOST=RDSエンドポイント,DB_NAME=RDSのDB名,DB_USER=RDSのマスタユーザ,DB_PASS=RDSパスワード" \
  --vpc --vpc.id VPCのID --vpc.ec2subnets サブネットのID --vpc.securitygroups セキュリティグループID \
  --vpc.publicip \
  test-app-env
```

`http://CNAMEのプレフィクス.ap-northeast-1.elasticbeanstalk.com/redmine` にアクセスしてRedmineが表示されればOK。
ElasticBeanstalkって作るまでは本当に簡単。カスタマイズは大変だけど。