elastic beanstalkとdockerhubを使って古いwebアプリをaws上で動かす

この記事は「[エムスリー Advent Calendar 2016](http://qiita.com/advent-calendar/2016/m3)」の 9日目の記事です:relaxed:

昔プライベートで作ったwebアプリがあるのだけど、こいつをaws上にさくっと持っていくにはどうすればいいか考えました。結構古いOSと言語バージョンなので、できればdocker化して本番でもdockerで動かしたい。ちょっと調べたら、awsのelastic beanstalkはdockerをサポートしているので、これがよさそうです。（docker使わなくても、beanstalkはrubyやphpなどメジャーな言語の新しめverはサポートしていますが、今回の対象アプリの環境はサポート外だったので、docker使いました）。ということで、以下の構成を試してみます

- dockerhubのプライベートレジストリを使う
- awsはelastic beanstalkとRDSを使う

![qiita docker aws.png](https://qiita-image-store.s3.amazonaws.com/0/4506/119d153f-f9ac-d48d-ab0c-60f8d2be0da6.png)



## dockerhub

プライベートレジストリを作って、イメージ化したソースコードをpushしておく。なお、DBはelastic beanstalkでRDSにつなぐ想定なので、接続情報は、環境変数化して外から注入できるようにしておく

```
RDS_HOSTNAME
RDS_PORT
RDS_USERNAME
RDS_PASSWORD
RDS_DB_NAME
```

## elastic beanstalk（以下、EB）

次はEBです

### dockerhubの認証情報をS3においておく（権限注意）

まず、EBがdockerhubからイメージを取得できるようにするために、dockerhubの認証情報を用意して、S3に置く

- 2016/12/8現在、古い形式しかサポートしてないので一手間必要
- 具体的には、`~/.docker/config.json`（ローカルPCでdocker loginしたときに作成されるファイル）の中身を以下の通り少し編集したファイルを作って、それをS3の非公開バケットに保存する

> 現時点では、Elastic Beanstalk は古い ~/.dockercfg 形式の設定ファイルを必要とします。config.json ファイルを変換するには、外側の auths キーを削除し、古い形式と一致するように JSON ドキュメントを平坦化します
http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_docker.container.console.html#docker-images-private


### Dockerrun.aws.jsonを作成

次に、docker動かすためのEB専用のファイル（Dockerrun.aws.json）を作成する

> Dockerrun.aws.json ファイルは、Docker コンテナを Elastic Beanstalk アプリケーションとしてデプロイする方法を記述するものです。この JSON ファイルは Elastic Beanstalk に固有です。ホストされたレポジトリで使用できるイメージでアプリケーションが実行される場合、Dockerrun.aws.json ファイルでイメージを指定し、Dockerfile を省略できますhttp://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_docker_image.html#create_deploy_docker_image_dockerrun

- 単一コンテナと複数コンテナが選べるが、今回は簡単な単一コンテナとする
- 公式サイトにあるように、どちらを選ぶかによってDockerrun.aws.jsonの書き方が異なる。単一コンテナの場合、v1形式となる

> 認証ファイルを [Dockerrun.aws.json] ファイルの [Authentication] パラメータ内に含む Amazon S3 バケットに関する情報を追加します。Authentication パラメータに有効な Amazon S3 バケットとキーが含まれていることを確認します。Amazon S3 バケットは、バケットを使用している環境と同じリージョンでホストする必要があります。Elastic Beanstalk は、他のリージョンでホストされている Amazon S3 バケットからファイルをダウンロードしません。
http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/create_deploy_docker_image.html#docker-singlecontainer-dockerrun-privaterepo

とあるので、こんなjsonを作る

```json
{
  "AWSEBDockerrunVersion": "1",
  "Authentication": {
    "Bucket": "バケット名",
    "Key": "ファイル名"
  },
...
```

### 新規アプリの作成

これで下準備はOK。AWSコンソールでEBの画面を開いて、以下のとおりアプリケーションを作っていく

新しいアプリケーションを作成

<img width="1068" alt="スクリーンショット 2016-12-09 19.40.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/4506/1b86431f-8951-6323-13ab-5a9aeff75a2d.png">

環境を作成（ウェブサーバー環境を選択）

<img width="853" alt="スクリーンショット 2016-12-09 19.42.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/4506/4c57ed26-7930-817f-5daa-0b60e0294217.png">

プラットフォームはdocker

<img width="814" alt="スクリーンショット 2016-12-09 19.42.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/4506/213e45b9-2b64-8fdd-1852-7f7e1b1e9f88.png">

アプリケーションコードはコードのアップロードを選択して、ここで、先ほど作った`Dockerrun.aws.json`をアップロードする

<img width="705" alt="スクリーンショット 2016-12-09 19.42.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/4506/3672c2b4-f6c0-1876-37ae-7c793db8c454.png">

しばらくたつと、デプロイ完了！表示されたurlにアクセスすると見れるようになってる！
便利すな〜

## RDS

次は上記のEBにRDSを紐付けます。以下に書かれている通りに作っていけばよいです
http://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/using-features.managing.db.html

※なお本番稼動させる場合、RDSの方を別に作っておいて、それをEBが参照するようにしたほうがよさそうです

> Elastic Beanstalk は、「Elastic Beanstalk 環境での Amazon RDS インスタンスの実行」をサポートします。この作業は環境の開発およびテストに適していますが、データベースインスタンスのライフサイクルをアプリケーション環境のライフサイクルに結び付けるため、実稼働環境に理想的なものではありません...環境からデータベースインスタンスを分離するには、Amazon Relational Database Service でデータベースインスタンスを実行し、アプリケーションの起動時にそれに接続するように設定します。これにより、複数の環境をデータベースに接続し、データベースに影響を与えないで環境を終了して、青/緑のデプロイメントでシームレスな更新を実行できるようになります


webアプリから接続できることを確認できたら、ローカルPCから接続する方法も一応試してみる

- 作成したRDSはデフォルトではローカルPCから接続できない
    - 一時的にアクセスするために、RDSのセキュリティを変更（あとで戻しておくこと）
    - 具体的には、RDSのセキュリティグループで「DBセキュリティグループ」の中に接続タイプ「CIDR/IP」で自分のIPを許可する（デフォルトだとDBセキュリティグループの中に「EC2 セキュリティグループ」しか設定されていないので、追加する）
- ローカルPCからmysqlコマンドでRDSに接続してみる

```
$ mysql -h xxx.xxx.xxx.rds.amazonaws.com -u <ユーザ名> -P <ポート> -p
  Enter password:
```

接続できた！接続できること確認したら、セキュリティ設定は戻しておく

## バッチは...

cronで動かしているようなバッチはどう動かせばいいかな。EBでは、cron.yamlというファイルでワーカー動かせるよう。SQSからhttp（POST）でキックされるエンドポイントを用意して動かすのかな。ここは別途調べるようということで、おしまい