Dockerを体験してみるハンズオン Part4

前回までのあらすじ

* [Part1 dockerをとりあえず動かしてみた](http://qiita.com/NewGyu/items/24290b79ecb606785edc)
* [Part2 dockerイメージがどんな管理になっているのか](http://qiita.com/NewGyu/items/e200c9fac28d4e2e3cb4)
* [Part3 自分でdockerイメージを作ってDockerHubに登録してみる](http://qiita.com/NewGyu/items/83610d2139a37b356e53)

今回は前回作ったDockerイメージをAmazon ECSにデプロイしてみます。
[Amazon ECSの概念的なところはこちらにまとめてみた](http://qiita.com/NewGyu/items/9597ed2eda763bd504d7)ので参考にしてください。

## Task Definitionを登録する

Task DefinitionはDockerコンテナの起動の仕方を定義するものです。([Docker Composeのcompose.ymlファイル](http://qiita.com/y_hokkey/items/d51e69c6ff4015e85fce)とだいたい同じです。)

### Create new Task Definition

[![https://gyazo.com/a8bb141059d98df7bf772c2eabf4f4fc](https://i.gyazo.com/a8bb141059d98df7bf772c2eabf4f4fc.png)](https://gyazo.com/a8bb141059d98df7bf772c2eabf4f4fc)

### Configure via JSON

ECSのコンソールからも登録できますが、実体はJSON形式の定義ファイルです。ここでは説明を簡略化するためにJSONを登録する手順にします。

[![https://gyazo.com/ed126065ed89fe74d8e736ac1dc9924e](https://i.gyazo.com/ed126065ed89fe74d8e736ac1dc9924e.png)](https://gyazo.com/ed126065ed89fe74d8e736ac1dc9924e)

```json:task-definition
{
    "family": "newgyu-docker",
    "containerDefinitions": [
        {
            "name": "hello",
            "image": "newgyu/docker-sample:1.0.0",　←ここを自分のイメージ名にする
            "memory": "256",
            "essential": true,
            "portMappings": [
                {
                    "hostPort": "80",
                    "containerPort": "80",
                    "protocol": "tcp"
                }
            ],
            "environment": null,
            "mountPoints": null,
            "volumesFrom": null,
            "extraHosts": null,
            "logConfiguration": null,
            "ulimits": null,
            "dockerLabels": null
        }
    ],
    "volumes": []
}
```

右からニュッとでてきた入力欄にJSONを貼り付けます。

| 項目  |      |
|---|------|
|family|Task Definitionの名前|
|containerDefinitions|n個のコンテナ定義を配列で定義|
|containerDefinitions.name|コンテナの名前|
|containerDefinitions.image|Dockerイメージ名[^image]|
|containerDefinitions.memory|コンテナに割り当てるメモリ量|
|containerDefinitions.portMappings|`docker run`するときの`-p`オプションと同でホストにバインドするポートの定義をn個の配列で指定|
|containerDefinitions.portMappings.hostPort|ホストのポート番号|
|containerDefinitions.portMappings.containerPort|コンテナのポート番号|

[^image]:イメージ名は` [REGISTRYHOST/][USERNAME/]NAME[:TAG]`の書式で`REGISTRYHOST`は省略可能（デフォルトは`hub.docker.com`）です。


細かい書き方についてはとりあえず[公式ドキュメントを見てね](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html)という形でお茶を濁しておきます。

## Clusterを作成する

### Create Cluster

[![https://gyazo.com/5412479cc7c2a511c199a1edb394c156](https://i.gyazo.com/5412479cc7c2a511c199a1edb394c156.png)](https://gyazo.com/5412479cc7c2a511c199a1edb394c156)

ここではとりあえず`for-docker-sample`という名前で作成します。

### ClusterとEC2インスタンスの紐付け

方法は非常に柔軟ですが、ここではAutoScalingグループを使った手順としますが、AutoScalingの作成は本筋ではないので手を抜いてポイントだけの解説にします。

#### 起動設定の作成

|項目|設定内容       |
|---|--------------|
|AMI|amzn-ami-2015.09.b-amazon-ecs-optimized - ami-3077525e|
|インスタンスタイプ|t2.micro（お金があればお好きなのを）|
|IAMロール|ecsInstanceRole|
|ユーザーデータ|紐付けたいクラスター名の設定をする[^user-data]|

[^user-data]:ここが最も重要なポイントでユーザーデータに下記の設定をします。

```bash:ユーザーデータ
#!/bin/bash
echo ECS_CLUSTER=for-docker-sample >> /etc/ecs/ecs.config
                 ^^^^^^^^^^^^^^^^
                 ここに紐付けたいクラスター名を指定する
```

セキュリティグループの設定はよしなにやってください。

#### Auto Scaling グループの作成

上記の起動設定を元に作成します。
~~ELBに紐付けたほうがよいでしょう。~~
ELBとAutoScalingGroupを紐付ける必要はありません。後述のServiceとELBを紐付けすることでECSがELBへのアタッチ／デタッチの面倒を見てくれます。

（すげー雑）

### ClusterにECSインスタンスが紐づく

[![https://gyazo.com/cf74eb0199653da1b8c6595f75c11a80](https://i.gyazo.com/cf74eb0199653da1b8c6595f75c11a80.png)](https://gyazo.com/cf74eb0199653da1b8c6595f75c11a80)

しばらくするとAuto ScalingグループがEC2インスタンスを起動し、Clusterの`ECS Instances`というタブに現れます。
仕組み的には`Amazon ECS Container Agent`が上記ユーザーデータで指定されたClusterに参加するように動作する感じです。

## Serviceを作成する

### Create Service 
[![https://gyazo.com/aa971fb577debefe3244efbcc24359b3](https://i.gyazo.com/aa971fb577debefe3244efbcc24359b3.png)](https://gyazo.com/aa971fb577debefe3244efbcc24359b3)

[![https://gyazo.com/d00ef9eb6efa04c697fc79db24df1c01](https://i.gyazo.com/d00ef9eb6efa04c697fc79db24df1c01.png)](https://gyazo.com/d00ef9eb6efa04c697fc79db24df1c01)

|項目| なんとなく説明   |
|---|----------------|
|Task Definition|Serviceの元となるTask DefinitionでTask Definitionは事前に作成されている必要があります|
|Cluster|Serviceを動作させるクラスタを指定します|
|Service name|Serviceの識別子で適当にわかりやすい名前をつけてください|
|Number of tasks|このService上でTaskをいくつ動かすかを定義します。あとから変更可能です。|
|Load Balancer|前述の通り負荷分散するためのELBの名前と使うポート番号を指定します。[^lb-port]|

[^lb-port]:ELBの`リスナー設定のインスタンスポート`とTaskDefinitionの`containerDefinitions.portMappings.hostPort`をひもづける感じになります。

[![https://gyazo.com/efe543f1083e1b64eed03124fcfc8ffa](https://i.gyazo.com/efe543f1083e1b64eed03124fcfc8ffa.png)](https://gyazo.com/efe543f1083e1b64eed03124fcfc8ffa)

### Serviceが起動する

[![https://gyazo.com/dc1cdf9f38db052f9891df426706c0a8](https://i.gyazo.com/dc1cdf9f38db052f9891df426706c0a8.png)](https://gyazo.com/dc1cdf9f38db052f9891df426706c0a8)
----

というところで今回は、前回作ったDockerイメージをAmazon ECSで動かしてみました。