ECS/Fargateに入門してみた

## 作成するアーキテクチャ

![ECS:Fargate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/84598903-2209-70d4-c3e8-059476394a2b.png)


## Dockerを本番環境で使うメリット

- エラーの発生を抑えられる。（ローカル環境や本番環境の差分を減らせるため、環境由来のエラーを防げる。）
- 環境構築のコストを下げられる。（docker build, docker runで一発で立ち上がる。）
- コードで管理できるため属人性を排除できる。（ファイルを管理すれば、コマンドで操作できるため誰がやっても同じ結果になる。）
- コードで管理できるためGitと併用できる。（Git,GitHubと連携してver管理ができる。）

## Docker基本コマンド

### ①docker run
docker imageからコンテナを一つ起動する。

### ②docker build
Dockerfileからイメージを作成。

### ③docker exec
コンテナ内のコマンドラインにアクセスする。


## AWS側の操作

マネジメントコンソールにアクセスした後下記の操作を行う。

#### ①ユーザ作成

rootユーザをそのまま使っていてはセキュリティ上まずいため別にユーザを作成する。

![スクリーンショット 2022-05-15 2.56.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/a0c16852-2c7f-b942-6d15-9bae43d0e95a.png)

IAMを起動した後左側にある「ユーザー」を選択。

![スクリーンショット 2022-05-15 3.03.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/5a7f0199-d06d-21b4-4d6b-3e029a115361.png)

右上のボタン「ユーザーを追加」をクリック。

![スクリーンショット 2022-05-15 3.08.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/a262d788-ba3e-69b7-7704-ab34c007d4b7.png)

ユーザ名：　yoshizumiadmin #(笑)
AWS 認証情報タイプを選択：　アクセスキー、パスワード両方にチェックを入れる
コンソールのパスワード：　*******
パスワードのリセットが必要： チェックを外す


![スクリーンショット 2022-05-15 3.18.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/3dbf6f18-2d18-cd28-2da2-41599073a54b.png)

AdministratorAccessを付与して

![スクリーンショット 2022-05-15 3.21.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/c9382c8a-ed2e-b49d-83cd-af4912129141.png)

ここまでできたら作成する。


![スクリーンショット 2022-05-15 3.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/6c0b80d0-3ba2-6f69-17a3-17b54859a876.png)


csvをダウンロードしてIAMユーザの作成は完了。
以降はこのユーザを使用してマネジメントコンソールにログインする。

```
$ aws configure

AWS Access Key ID [******************NW]: 
AWS Secret Access Key [******************XF]: 
Default region name [ap-northeast-1]:
Default output format [None]: json
```
上記のように設定してAWS-CLIの設定を終える。

#### ②ECSロール作成
他のAWSサービスと連携するためにもECSにIAMロールを割り当てる。
ECS関連の３つのロールを作成する。
![スクリーンショット 2022-05-15 9.53.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/36ca998d-5c7e-5f3c-3c35-9d994251a050.png)

左のタブから「ロール」を選択。

![スクリーンショット 2022-05-15 16.43.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/dd66c3dd-ba45-7f2e-e337-11a0cfd551c2.png)
画像のような具合に3つ作成していく。

②つ目のロール
![スクリーンショット 2022-05-15 16.49.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/04cb1277-029a-4c7a-6b60-4e9c036e2a0f.png)


③つ目のロール
![スクリーンショット 2022-05-15 18.14.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/3b897677-3de5-661b-dfae-e44f00af9f48.png)

「task」で検索をかけて、ポリシーを絞ることを忘れない。
３つロールを作成したら、この手順は完了。


#### ③VPCの作成

![ECS:appdb.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/f89bc8c5-d29a-f74d-fc1a-9155c3119ebd.png)
作成するVPCのイメージ

![スクリーンショット 2022-05-15 23.08.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/3b6d9a30-301d-35b0-7bcf-f6eb137ad3bb.png)
マネジメントコンソールからサービス検索⇨「VPC」を検索⇨「VPCを作成」
名前：ecs-vpc
IP v4CIDR:10.0.0.0/16
あとはデフォルトで作成。この中にパブリックサブネットを二つ作成する。（DBをプライベートサブネットに作成しないのは、あくまで練習用のため）

public-subnet1:AZ-1a,CIDR:10.0.0.1/24
public-subnet2:AZ-1c,CIDR:10.0.1.0/24
あとはデフォルトでサブネットを２つ作成する。
（書き忘れてたけど、インターネットゲートウェイも作成してください！笑）

![スクリーンショット 2022-05-15 23.26.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/2eec7c0c-f165-7c36-f7fd-d879e357940f.png)
ルートテーブルをIGW向けに作成してインターネットとの通信を可能にする。
先ほど作成したサブネットとの関連付けをしてこの手順を完了する。


#### ④ECRにDockerfileをアップロード

アップロードするDockerfile
```Dockerfile
FROM php:7.4.24-apache

# PHPのモジュールなどをインストール
RUN apt-get update \
  && apt-get install -y zlib1g-dev \
  && apt-get install -y zip unzip \
  && apt-get -y install libzip-dev libonig-dev \
  && docker-php-ext-install pdo_mysql mysqli zip \
  && docker-php-ext-enable pdo_mysql mysqli \
  && a2enmod rewrite

# タイムゾーン設定
ENV TZ=Asia/Tokyo

# cronのインストール
RUN apt-get update && apt-get install -y \
  busybox-static \
  && apt-get clean

# composerをインストール
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/bin/ --filename=composer
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin

# アプリケーションフォルダを環境変数として設定
ENV APP_HOME /var/www/html

# apacheのuidとgidをdocker user uid/gidに変更。
RUN usermod -u 1000 www-data && groupmod -g 1000 www-data

#change the web_root to laravel /var/www/html/public folder
# RUN sed -i -e "s/html/html\/public/g" /etc/apache2/sites-enabled/000-default.conf
COPY ./php/vhost.conf /etc/apache2/conf-enabled/vhost.conf

#  apache module rewrite を有効にする
RUN a2enmod rewrite

# ソースコードと.envファイルをDockerImageに埋め込む
COPY . $APP_HOME
COPY .env.production /var/www/html/.env
# 初回起動時に行うスクリプトファイルをコピーして実行権限を与える
COPY ./php/start.sh /var/www/html/start.sh
RUN chmod 744 ./php/start.sh

# 必ずキャッシュ用のディレクトリを作っておくこと→ Fargateの場合ずっとキャッシュが残ることになる
RUN mkdir bootstrap/sessions && \
    mkdir storage/framework/cache/data

# フレームワークに必要なモジュールをDockerImageにインストール
RUN composer install --no-dev --no-interaction

# 書き込み権限を与える
RUN chown -R www-data:www-data $APP_HOME
# RUN chmod -R 777 storage && \
#     chmod -R 777 bootstrap
# CMD php artisan migrate --force
CMD ["bash", "start.sh"]
```
※細かいDockerfileの解説は省きます。

DBのDockerfileも作成しておく。

```Dockerfile
FROM mysql:5.7.30

COPY ./init.sql /docker-entrypoint-initdb.d
```

※シェルスクリプトを書いてbuildの際に走らせる。

```start.sh
#!/usr/bin/env bash
php artisan migrate --force
chmod -R 777 bootstrap 
chmod -R 777 storage
/usr/sbin/apache2ctl -D FOREGROUND
```

マネジメントコンソールからECSを検索し、右側のタブからリポジトリを選択
![スクリーンショット 2022-05-16 0.31.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/e8d1f36f-ec52-c5a4-a21a-af3adedac561.png)

![スクリーンショット 2022-05-16 0.35.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/b13b53ef-e5e0-ab61-f43a-1cac88ff5f02.png)

プライベートのlaravel-ecsというリポジトリを作成する。
イメージスキャンの設定を有効にしておくことを忘れない。
リポジトリを作成する。

![スクリーンショット 2022-05-16 0.44.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/34ab7640-b866-3c04-7d2a-12268919f527.png)
右上の「プッシュコマンドを表示」で表示されたコマンドをターミナルから実行する。

![スクリーンショット 2022-05-16 0.43.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/9ee95b26-29e5-d7f8-e8ad-eba5e892a92f.png)
無事ログインできたことが分かる。

先ほど作成したDockerfileがあるディレクトリに移動したあと、ECR「プッシュコマンドの表示」で表示されるコマンドを順に実行していく。

①aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com

②docker build -t laravel-ecs .
![スクリーンショット 2022-05-19 21.33.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/332907bd-8926-f50b-ef37-001958705602.png)
うまくbuildできている。

③docker tag laravel-ecs:latest 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-ecs:latest
tag付けをしている。

④docker push 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com/laravel-ecs:latest

![スクリーンショット 2022-05-19 21.54.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/e5ca3b03-7173-c249-bc87-10bf6daa2dde.png)
無事pushされていることがわかる。
同様にしてDBのリポジトリを作成していく。

![スクリーンショット 2022-05-19 23.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/2012f3b0-4164-521c-5c50-33e4c7e5b886.png)
名前だけ変えて作成する。
次は同様にしてイメージをプッシュしていく。

①aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com

②docker build -t mysqlecs .
![スクリーンショット 2022-05-19 23.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/c3e52bba-4f1b-089d-0ff0-916c24572875.png)
今度はすぐbuildされる。

③docker tag mysqlecs:latest 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com/mysqlecs:latest

④docker push 071667546372.dkr.ecr.ap-northeast-1.amazonaws.com/mysqlecs:latest
![スクリーンショット 2022-05-20 0.07.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/601f3a12-8783-e232-e27f-ef61de1cec92.png)
こちらも無事pushできた。

## Fargateの操作
※ローカルにDockerのインストールが済んでいない場合はインストールする。

①クラスター作成
![スクリーンショット 2022-05-20 0.16.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/0010dd8d-e0e2-2bc1-efb2-06907e604940.png)
マネジメントコンソールからECSを開き、「クラスター」⇨「クラスターの作成」をクリック。

![スクリーンショット 2022-05-20 0.18.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/d2b2cf09-8b24-10d6-1987-471a9e8033c1.png)
「ネットワーキングのみ」を選択。

![スクリーンショット 2022-05-20 0.21.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/4fad2d8a-fcde-88f6-e90c-2bd33df07c86.png)
クラスター名をつけてクラスター作成。

![スクリーンショット 2022-05-20 0.31.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/3db72151-fae6-9716-4e72-3344d09fcbc8.png)
無事に作成されている。

②タスク定義

![スクリーンショット 2022-05-20 1.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/8940b01f-476b-580d-4824-48ba12e466ec.png)
左側のタブから「タスク定義」を選択。
「新しいタスク定義の作成」⇨「起動タイプの互換性の選択」：Fargateを選択して次のステップ。

![スクリーンショット 2022-05-20 1.19.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/5ac0e4fc-a0f1-75a9-1f86-50ff3c568915.png)
タスク定義名:simpleapp
タスクロール:AmazonECSTaskExecutionRole
オペレーティングシステムファミリー:Linux
タスクメモリ (GB):0.5GB
タスク CPU (vCPU):0.25vCPU
「コンテナの追加」⇨コンテナ名：laravel⇨イメージ：先ほど作成したECRのリポジトリURI
メモリ制限 (MiB):128
ポートマッピング:80

あとはデフォルトで「作成」

![スクリーンショット 2022-05-20 1.29.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/8d4bd4e7-b604-8dfa-d0a1-1d61fe01b2a3.png)
作成には成功している。

③サービス作成
![スクリーンショット 2022-05-20 1.34.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/0c7f4bf7-6090-0a0c-0cc0-e86527280a28.png)


起動タイプ:FARGATE
オペレーティングシステムファミリー:Linux
リビジョン:latest
プラットフォームのバージョン:LATEST
クラスター:simple-ecs
サービス名:simple-ecs-service
タスクの数:１
デプロイメントタイプ:ローリングアップデート
あとはデフォルトで「次のステップ」

クラスター VPC:先ほど作成したVPC
サブネット:先ほど作成したサブネット２つ

あとはデフォルトで「次のステップ」
Autoscaling:何も変更せずに「次のステップ」

![スクリーンショット 2022-05-20 1.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/b031c881-87aa-2b36-4d0a-12a2d53827a9.png)
無事作成されている。

![スクリーンショット 2022-05-20 2.02.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/2ad85b16-224f-afe7-524f-420c6ba970ff.png)
パブリックIPからアクセスを試みる。

![スクリーンショット 2022-05-20 2.00.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/d3de2a33-b393-e407-bb8f-9b4604eb962e.png)
エラーが表示される。なんでだ！

![スクリーンショット 2022-05-20 2.40.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280830/00ae746b-b10e-0c1a-5467-22822494a26c.png)

DBとうまく接続できていませんでしたね。これで完了です！！