ECSへのデプロイが驚くくらい簡単になっていた...

この記事は株式会社アトラエのアドベントカレンダー9日目の記事です。

本日は新卒１年目の岩澤が書きます。
普段はyentaというビジネスマッチングアプリでサーバーサイドエンジニアをしています。

## DockerとAWSが共同でECSへのデプロイをサポート
僕は普段インフラを触る機会が少ないこともあり、デプロイと言われると少し難しいイメージがあります。特にAWSを使う場合にはECR、ECS、EKS、RDS、ロードバランサーなどなどアプリの初めてのデプロイとなると設定や必要な知識も多いかと思います。

そんな中でこの前の7月にDockerとAWSが共同でECSへのアプリケーションのデプロイを簡単にしてくれたという発表(『[Docker と AWS が共同で AWS Fargate 上の Amazon ECS へのアプリケーションのデプロイをサポート』](https://aws.amazon.com/jp/about-aws/whats-new/2020/07/docker-and-aws-collaborate-to-help-deploy-applications-to-amazon-ecs-on-aws-fargate/))が出ていたので、今回はそちらを紹介していこうかと思います。

## 発表の概要
先に今回できるようになったことの概要だけを説明すると、おそらくlocalの開発でみなさん使っているであろう`docker-compose.yaml`の内容を元に`docker compose up`と打ったらAWS Fargate上のECSにデプロイされるというものです。

...こいつ打ち間違えてるよって思った方も多いかもしれないですが、タイポじゃないです。（笑）いつも見慣れている`docker-compose up`ではなく`docker compose up`なので注意が必要ですね。
これを聞いてややこしいなって思った方も含めて興味を持っていただいた方は最後まで読んでいただけると幸いです。

## 今回デプロイするアプリケーション

今回デプロイするアプリケーションはAWSの公式でも使われている[Yelb](https://github.com/mreferre/yelb)というアプリケーションにしました。
構成としては下記の画像のようになっており、複数のコンテナにまたがってアプリケーションが動いているため今回の例としてはぴったりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/b77b9771-0499-4753-d1af-a9c136516a71.png)
まずlocalでの挙動を確認します。

```terminal
$ git clone https://github.com/mreferre/yelb.git
$ cd ./yelb/deployments/platformdeployment/Docker/
$ docker-compose up
```

この後に`localhost`にアクセスすると以下の画像のような画面が表れているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/88f69fca-2f05-3905-dbaa-aabf9b661ad4.png)

## AWSの設定
デプロイするためにAWSの設定を行います。
まずは[こちら](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/get-set-up-for-amazon-ecr.html)の記事を参考にIAMの設定をします。すでにIAMの設定をされている場合設定は不要ですが、ここで下記のアクセスが許可されていないとデプロイできないので気をつけます。

- cloudformation:*
- ecs:ListAccountSettings
- ecs:CreateCluster
- ecs:CreateService
- ec2:DescribeVpcs
- ec2:DescribeSubnets
- ec2:CreateSecurityGroup
- ec2:DescribeSecurityGroups
- ec2:DeleteSecurityGroup
- iam:CreateRole
- iam:AttachRolePolicy
- iam:DetachRolePolicy
- iam:DeleteRole
- elasticloadbalancing:*
- application-autoscaling:*
- servicediscovery:*
- logs:CreateLogGroup
- logs:DescribeLogGroups
- logs:FilterLogEvents
- logs:DeleteLogGroup
- route53:CreateHostedZone
- route53:DeleteHostedZone
- route53:GetHealthCheck
- route53:GetHostedZone
- route53:ListHostedZonesByName

IAMの設定ができたら以下のコマンドを入力してECSにデプロイをするためのcontextを生成します。

```terminal
$ docker context create ecs myecscontext
```

すると下記のようにいくつか質問が出るのでさっき作ったIAMのprofileを選択します。

```terminal
? Create a Docker context using: An existing AWS profile
? Select AWS Profile user
Successfully created ecs context “myecscontext”
```

コンテキストは[こちら](https://matsuand.github.io/docs.docker.jp.onthefly/engine/context/working-with-contexts/#introduction)に詳細の説明がありますが、エンドポイントやセキュリティ情報などを管理しています。

```terminal
$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
myecscontext        ecs
```

contextの一覧と現在のcontextを確認できます。
今回の場合defaultのcontextを使っており、これはECSではなくlocalの環境のためのcontexであるため、この状態で`docker compose up`コマンドを間違って叩いてしまったとしてもエラーがでてデプロイされることはありません。

```terminal
$ docker compose up
Command “compose up” not available in current context (default)
```

contextを変えて改めてデプロイします。

```terminal
$ docker context use myecscontext
myecscontext
$ docker compose up
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/075996e0-0313-8f03-e0c1-53e0a93d31f6.png)
少し見づらいですが、画像のようにデプロイが完了すれば成功です！

## デプロイを確認する
デプロイが完了した後にAWSのコンソールから`Cloud Formation`を開きます。
すると１つスタックが追加されているのがわかると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/dc7b2f37-44e5-c99c-c06c-afb36d04a5e3.png)
これは`docker compose up`のコマンドがdocker-compose.yamlからCloudFormationを構築してそれを使ってデプロイを行なっているためです。
実際に中身をみてみるとECSやLoadBalancerなど25のリソースが作られていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/2a2048ec-e692-2e15-136e-437fadf26a60.png)
またターミナルに戻って

```terminal
$ docker compose ps
ID                                         NAME                REPLICAS            PORTS
docker-RedisserverService-bs6RqrSUuIux     redis-server        1/1
docker-YelbappserverService-yG2xExxLjU6D   yelb-appserver      1/1
docker-YelbdbService-RDGo1mRenFMt          yelb-db             1/1
docker-YelbuiService-X0bPBdwZmNcC          yelb-ui             1/1                 docke-LoadB-C7CWCW0SZZCC-240648981.us-east-1.elb.amazonaws.com:80->80/http
```

ここの一番下に出ているPORTSにアクセスすると先ほどlocalでみたのと同じ画面が表示されました！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609824/0998c92a-0b14-3f76-be34-1c49f94736e6.png)

## 感想
コマンドは少しややこしいですが、コマンド一つで面倒くさい詳細な設定をなしにアプリケーションをデプロイできるのはすごく嬉しい！docker-compose.yamlから自動でCloudFormationを作ってくれるので細かくContainer分けていってもインフラやデプロイで手間が掛からなくて良いなと思いました。
一方で現在だとEC2でなくFargateでしか作れないことや、細かい設定をしたいときは結局GUIでしかできないこと、RDSを使いたい場合やECRを使いたい場合は今まで通り設定を行わなければならないのでそちらも自動化されていったらさらにアプリ開発だけに集中する環境が作られると感じているのでさらなる進化や浸透に期待しています。