AWS Elastic Beanstalk + docker + playframeworkでサイト構築


AWS Elastic Beanstalk + docker + playframeworkで動作環境を作ってみました。

### 1. AWS Elastic Beanstalk

Elastic Beanstalkは、WEB環境を簡単にスケーラブルに作れるAWSのプロダクトのようですがWebサービスを構築する上でどのサービスを選択すればよいかの調査のため試してみました。
ブロクに載せていますが、現時点で最善策を調べきれずに書いているのでもっと良いやり方があるかもしれませんがお許しください。

##### 1-1. Elastic Beanstalkのアプリケーションの作成

AWSコンソールより新しいアプリケーションの作成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/f31bab28-a7a6-b156-6070-794dda24dd79.png)

Elastic Branstalkの環境を作ります。目的がウェブなのでウェブサーバー環境を選びました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/40d43595-50db-2d57-b64c-ea35bbfc6757.png)

環境の作成では、ホスト名、プラットフォームを設定します。アプリケーションコードは新規に作成するのであれば「サンプルアプリケーション」から作成して上書くのがお勧めです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/2e76ebf5-4265-c109-7c14-35a5cdba2dba.png)

環境の作成をするとec2のインスタンスが作成されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/bad9a0c9-eaee-4f45-c9c6-f2843081d65f.png)

サンプルアプリケーションが動きました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/1b4304c8-0e79-c8fd-cc89-a5b5df064898.png)

作成が完了するとaws cliからログインしてdockerイメージをpushする手順が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/dc63dff3-c58d-c113-9111-2391939483fe.png)

### 2. AWS ECR

Dockerのデプロイは、Dockerfileをアップロードするか、Dockerrun.aws.jsonという定義ファイルをアップロードします。
しかし、Dockerfileとデプロイアーカイブをどう配置したらうまく起動してくれるのかわからなくAWS Elastic Container Registoryを使いました。
AWSコンソールから、ECRはECS(Elastic Container Service)の中にあります。

リポジトリを作成します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/939bdfac-76ec-0e7f-3540-e7d618c425d2.png)

リポジトリを作成するとaws cliを使ってecrにログインする方法とdockerイメージの作り方、pushコマンドが表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/a3cd315a-5ddf-0923-3e20-4682f16f8bdf.png)

参考URL: https://qiita.com/kazuyoshikakihara/items/f87b4b377b5844f09614

### 3. AWS s3

DockerのデプロイアーカイブをDockerfileと一緒にあげる方法がわからなかったのでDockerイメージをECRに登録しました。
ECRのイメージをDockerrun.aws.jsonに記述するのですが認証情報をs3に置かなければなりません。

ECRのログイン情報がaws cliにてECRにログインしていれば次のファイルに格納されています。

```shell
~/.docker/config.json
```

参考にしたブログではaws cliでs3を作っていました。

##### 3-1. S3 Bucket を作成する

```shell
$ aws --region us-west-2 s3 mb s3://kaorunix-docker-auth
```

##### 3-2. S3 Bucket に認証情報をアップする

```sehll
$ aws --region us-west-2 s3 cp ~/.docker/config.json s3://kaorunix-docker-auth/playsample-docker-auth.txt
```

##### 3-3. IAM roleにポリシーを追加

Elastic BeanstalkインスタンスにS3へのアクセスを許す必要があります。
マネージドポリシーの AmazonS3ReadOnlyAccess をアタッチします。

AWSコンソールでIAM、ロールを開く

Elastic Beanstalkを作成するときに作成したロールサービスのロール(arn:aws:iam::xxxxxxxxxxx:role/aws-elasticbeanstalk-service-role)を選択。ポリシーを選択してアタッチします。


参考URL: https://inokara.hateblo.jp/entry/2016/01/16/191633


### 4. playframeworkが中で動くdockerイメージ作成

稼働したElastic Beanstalkを置き換えるdokcerイメージを作成します。

##### 4-1. playframeworkの実行アーカイブを作る

実際はプロジェクトを作って実装してからですが、お試しなのでプロジェクト作成しただけでDockerイメージ作ってしまいます。
ただし、いくつか設定をしないと動かないところがあったので載せておきます。

###### application.confの設定

play.http.secret.keyはここに書く必要があるのかわかりませんが次のコマンドで更新しました。起動時に秘密鍵がないと起動できませんでした。

```
$ sbt playUpdateSecret
```

また、接続元ホストの設定を `allowed = ["."]` と記載しないと `502 Bad Request` が返りました。

```dockerfile

play.http.secret.key="xxxxx"
play.filters.hosts {
  allowed = ["."]
}
```

###### playプロジェクトのリリースアーカイブを作る

playプロジェクトのディレクトリで次のコマンドを実行し、リリースアーカイブを作る。

```shell
$ sbt dist
```
リリースアーカイブが次のパスにできるので、任意のディレクトリで展開します。

```
プロジェクトディレクトリ/target/universal/playsample-1.0-SNAPSHOT.zip
```

###### Dockerfile作成

リリースアーカイブを展開し、展開したディレクトリに次のDockerfileを作成。

```dockerfile
FROM openjdk:8u151-jre
COPY . /root/
RUN chmod +x /root/bin/playsample
CMD ["/root/bin/playsample", "-Dplay.http.secret.key=P0Bz?>b;hYPO8cC=u:sfFacry_x5qVpdh`SpaHEvtYNtQM]YdZfwU<eIM1qVTMfy", "-Dhttp.port=80"]
```

Dockerfileの意味は以下の通り。

* playflameworkが動くようにjavaの入ったDockerイメージを元にする。

```dockerfile
FROM openjdk:8u151-jre
```

* アーカイブしたファイル群をDockerイメージの中にコピー

```dockerfile
COPY . /root/
```

* 実行権限をつける

```dockerfile
RUN chmod +x /root/bin/playsample
```

* playframework playsampleプロジェクトを常駐プロセスとして起動する。

```dockerfile
CMD ["/root/bin/playsample", "-Dplay.http.secret.key=xxxxxxx", "-Dhttp.port=80"]
```

Dockerfileを準備したら1-1で示されたコマンドを順に実行します。

aws cliでECRにログインします。

```shell
$(aws ecr get-login --no-include-email --region us-west-2)
```

Dockerイメージを作成します。

```shell
$ docker build -t astrolab-work .
```

Dockerをリモートのリポジトリにpushできるようにタグをつけます。

```
$ docker tag playsample:latest xxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/playsample:latest
```

ECRへのpush

```
$ docker push xxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/playsample:latest
```

#### 5. AWS Elastic Beanstalkへのデプロイ

###### 5-1. Dockerrun.aws.configの作成

次のような内容で作成

```json
{
    "AWSEBDockerrunVersion": "1",
    "Authentication": {
        "Bucket": "kaorunix-docker-auth",
        "Key": "playsample-docker-auth.txt"
    },    
    "Image": {
    "Name": "xxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/playsample:latest",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": "80"
    }
  ],
  "Volumes": [
    {
        "HostDirectory": "/tmp",
        "ContainerDirectory": "/tmp/tmp"
    }
  ],
  "Logging": "/var/log/play"
}
```

###### 各説明

Elastic BeanstalkからECRへのアクセス権を記載したファイルの指定。s3のバケットとファイル名で指定する。

```
    "Authentication": {
        "Bucket": "kaorunix-docker-auth",
        "Key": "playsample-docker-auth.txt"
    },    
```

ECRのリポジトリ名を指定する。

```
  "Image": {
    "Name": "xxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/playsample:latest",
    "Update": "true"
  },
```
予想だが、EC2のボリュームをDocker内にマウントできるのではないだろうか。

```
  "Volumes": [
    {
        "HostDirectory": "/tmp",
        "ContainerDirectory": "/tmp/tmp"
    }
  ],
```

ログ出力するパスを指定していると思うが、今回ログ出力設定を行っていないので出力されていない。また、設定するとeb cliでログにアクセスできると予想する。

```
  "Logging": "/var/log/play"
```


###### 5-2. Elastic Beanstalkアプリにアップロードする

AWSコンソールより、デプロイ先のアプリケーション名、環境名を辿り次の画面に移動する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/f87e67b4-97a9-e11f-d0d2-431725414667.png)

アップロードとデプロイボタンを押下し、選択ボタンを押下するとファイルを選択するダイアログが開くのでDockerrun.aws.configファイルを選択する。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/d029c864-e3fc-6d84-3d64-26c7b80322af.png)

バージョンは任意の作成したDockerアプリケーションのバージョンなどを入れる。
しばらくデプロイ中の状態になり、完了したら画面上部にあるURLをクリックすると次の画像のようにDockerで動いているアプリケーションが表示される。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/284697/bc71870b-b47e-3078-24fe-01523e760308.png)

---


#### ec2またはDockerへの接続

#### 1. eb cliの設定

ebをインストールして設定を実施。

参考URL https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb-cli3-configuration.html

ebのsshの設定をする。次のコマンドを実行し、質問のなかでsshのキーを紐づける。

```shell
$ eb ssh —setup
```

キーを紐づけるとsshで接続できるようになりました。

```shell
ssh -i ${KEY} ${EC2 hostname}
```

#### 2. dockerへの接続

dockerは、ec2の中で実行されているのでログインできれば普通にdockerのコマンドが実行できる。