[AWS] Amazon ECS(EC2タイプ)のちょっと長めのチュートリアル(第1回)

Amazon ECS(Elastic Container Service)は、クラスタ上でのDockerコンテナの実行・停止・管理を簡単におこなえる、スケーラブルで高速なコンテナ管理サービスです。

コンテナサービスの種類としては、コントロールプレーン(=コンテナ管理をする場所)でECSとEKS、データプレーン(=実際にコンテナが稼働する場所)でEC2とFargateの選択が可能です。

図は [参考資料] (https://www.slideshare.net/AmazonWebServices/develop-containerized-apps-with-aws-fargate-srv314-chicago-aws-summit) より：EKSとFargateの組み合わせは長らく"comming soon"のままになっているため、現状選択可能な組み合わせは3通りです。本記事は、一番左のECS(EC2タイプ)の構築手順について説明したものです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/a0daa82a-dc59-8ac7-39ea-25a7ad8c4ccb.png" width=800px>

# 説明のポイント

ECSの構成図としては、こんな感じの図がよく出てくるかと思います。ECSの用語としてクラスター(Cluster)、サービス(Service)、タスク(Task)などを覚える必要があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/4618fb76-33e8-f16a-5f65-d7e47a800ce9.png" width=800px>

一方で、EC2タイプの場合、実際に作成されるAWS環境(運用する上で見るべきもの)はこんな構成です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/83e983ed-3c05-bad5-5b63-2d082bcf52f7.png" width=800px>

2つの関連を理解するまでに時間がかかったので、説明してみようと思ったのが本記事の趣旨となります。
手順はちょっと長くなるので、何回かに分けて書きます。

# 1) ECRの作成とコンテナイメージのPush

まずはテスト用のDockerイメージを作成して、ECRリポジトリにプッシュします。
図では赤枠の部分で、ここはあまり違いの無い部分です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/0d7cfe4f-fcbc-9033-221e-bdde803aca00.png)

## イメージの作成

nginx のイメージを使ってみます。簡単ですが、テスト用のhtmlを追加しています。

```dockerfile:Dockerfile
FROM nginx
COPY demo.html /usr/share/nginx/html/demo.html
```

```shell
# ls -l
total 8
-rw-r--r-- 1 root root 379 Jun 13 14:08 demo.html
-rw-r--r-- 1 root root  59 Jun 13 14:04 Dockerfile

# cat Dockerfile
FROM nginx
COPY demo.html /usr/share/nginx/html/demo.html

# cat demo.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>ECS demo page</title>
  </head>
  <body>
    <div class="main_page">
      ECS Demo Page
    </div>
  </body>
</html>

## ※Dockerコンテナをビルドする※
# docker build -t nginx-demo01 .
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM nginx
 ---> 958a7ae9e569
Step 2/2 : COPY demo.html /usr/share/nginx/html/demo.html
 ---> de6344632e81
Removing intermediate container 8f3ace3b0132
Successfully built de6344632e81
Successfully tagged nginx-demo01:latest

## ※動作確認のため実行してみる※
# docker run -itd --privileged -p8888:80 nginx-demo01
50b1153248f2f343eca96465c5e74e3e7f02f68370a6ce181e98714174a8a725

## ※起動したことを確認する※
# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
50b1153248f2        nginx-demo01        "nginx -g 'daemon ..."   11 minutes ago      Up 11 minutes       0.0.0.0:8888->80/tcp   awesome_colden

## ※追加したdemo.htmlが参照できることを確認する※
# curl http://localhost:8888/demo.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>ECS demo page</title>
  </head>
  <body>
    <div class="main_page">
      ECS Demo Page
    </div>
  </body>
</html>

## ※動作確認したコンテナを停止しておく※
# docker stop 50b1153248f2
50b1153248f2
```

## ECRリポジトリの作成

AWSコンソールの サービス → ECR → リポジトリの作成 から作成します。入力する情報は名前だけです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/790a4ab7-4d26-0bec-6c96-a8406d8e6104.png)


## イメージのPush

作成したリポジトリを表示すると、右上に「プッシュコマンドの表示」というボタンがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/d3cf9a48-583b-df35-7b1a-9749b23dfc0a.png)

ボタンを押すと、この後実行すべきコマンドがリポジトリ名入りで表示されるので大変便利です。これを参考に残りの作業をおこないます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/eb86841e-bdab-f70f-dc3f-d2c93e0423d3.png)

ビルドは既に実施したので残りの作業をおこなっていきます。

ECRへのログイン：profileオプションが他のコマンド同様に指定可能です。

```shell
# $(aws ecr get-login --no-include-email --region ap-northeast-1 --profile vatest)
Login Succeeded
```

タグ付け：先ほどビルドしたイメージに、ECR形式でのタグを付与します。ECR形式はアカウントIDとリージョンが入っていて、結果が横長になってしまうのが難点です。

```shell
# docker tag nginx-demo01:latest <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-demo01:latest
# docker images
REPOSITORY                                                          TAG     IMAGE ID      CREATED          SIZE
<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-demo01  latest  de6344632e81  26 minutes ago   109MB
nginx-demo01                                                        latest  de6344632e81  26 minutes ago   109MB
```

ECRへのプッシュ：先ほど付与したタグの通りに指定し、ECRにプッシュします。

```shell
# docker push <AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-demo01:latest
The push refers to a repository [<AWSアカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-demo01]
e0ea43f667cc: Pushed
a552ca691e49: Pushed
7487bf0353a7: Pushed
8781ec54ba04: Pushed
latest: digest: sha256:01f1c2fe5352e1d2db25db934211a4da224999ea80a0c5e400d4125ff4ef2845 size: 1155
```

最後に、コンソールでイメージが追加されたことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172826/9e4b7bce-e980-9afd-2e43-27626ed1a782.png)

以上で、ECRへのイメージのPushができました。次回はこのイメージを動作させるためのECSクラスターを作成してみます。


# 参考資料
- [Deep Drive on AWS Fargate] (https://www.slideshare.net/AmazonWebServices/develop-containerized-apps-with-aws-fargate-srv314-chicago-aws-summit)