Laradock + Nuxt(SSRモード)をAWS Fargateで実行する

# 前提
[同一リポジトリでLaradock ＋ Nuxt(SSRモード)の環境構築](https://qiita.com/gemetasu1103/private/3a6d495b37623dc2e89a)
上記のサイトでLaradock+Nuxtで環境構築できていること

# 参考サイト

# 手順

1. リポジトリにDocker関連のファイルを追加し修正する
2. DockerfileとDocker-composeの修正する
3. ECRにリポジトリを作成する
4. Dockerをビルドし、イメージをECRへpushする
5. Laravel+NuxtプロジェクトをFargateに乗せる

# 1. リポジトリにDocker関連のファイルを追加し修正する

Dockerイメージをビルドするために必要なファイルをlaradockからコピーしてくる

```sh
cd ./{プロジェクト名}
mkdir docker
cp -r ../laradock/nginx ./docker/nginx
cp -r ../laradock/php-fpm ./docker/php-fpm
cp ../laradock/docker-compose.yml docker-compose.yml
touch ./docker/php-fpm/startup.sh
```

# 2. DockerfileとDocker-composeの修正する

AWSの本番環境に乗せるために
リポジトリ内のDockerfileを編集する

./{プロジェクト名}/docker/nginx/Dockerfile

```dockerfile
FROM nginx:alpine

LABEL maintainer="Mahmoud Zalt <mahmoud@zalt.me>"

# nginxの設定ファイルをコンテナ内に配置する
COPY ./docker/nginx/nginx.conf /etc/nginx/
COPY ./docker/nginx/sites/ /etc/nginx/sites-available/
COPY ./docker/nginx/ssl/ /etc/nginx/ssl/
COPY ./docker/nginx/sites/default.conf /etc/nginx/conf.d/

# If you're in China, or you need to change sources, will be set CHANGE_SOURCE to true in .env.

ARG CHANGE_SOURCE=false
RUN if [ ${CHANGE_SOURCE} = true ]; then \
    # Change application source from dl-cdn.alpinelinux.org to aliyun source
    sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/' /etc/apk/repositories \
;fi

RUN apk update \
    && apk upgrade \
    && apk add --no-cache openssl \
    && apk add --no-cache bash \
    # gitをダウンロード
    && apk add --no-cache git \
    && adduser -D -H -u 1000 -s /bin/bash www-data

# AWS fargateではdepends_onやlinkでのコンテナ通信を行えないため、コンテナ名(php-fpm)では接続できない
# そのため127.0.0.1で通信を行う
ARG PHP_UPSTREAM_CONTAINER=127.0.0.1
#ARG PHP_UPSTREAM_CONTAINER=php-fpm
ARG PHP_UPSTREAM_PORT=9000

# Set upstream conf and remove the default conf
RUN echo "upstream php-upstream { server ${PHP_UPSTREAM_CONTAINER}:${PHP_UPSTREAM_PORT}; }" > /etc/nginx/conf.d/upstream.conf \
    && rm /etc/nginx/conf.d/default.conf


# nginxコンテナ内でNuxtをSSRモードで立ち上げるためにnpmをインストールする
RUN apk add --update nodejs nodejs-npm

# ワーキングディレクトリの指定
WORKDIR /var/www

# ソースコードをコンテナにコピーする
COPY . .

# Nuxtをビルドする準備をする
RUN npm install

# foreverモジュールを入れて、Nuxtサーバをバックグラウンドで起動できるようにする
RUN npm install -g -y forever

ADD ./docker/nginx/startup.sh /opt/startup.sh
RUN sed -i 's/\r//g' /opt/startup.sh
CMD ["/bin/bash", "/opt/startup.sh"]

EXPOSE 80 443

```

./{プロジェクト名}/docker/php-fpm/Dockerfile

```dockerfile
#
#--------------------------------------------------------------------------
# Image Setup
#--------------------------------------------------------------------------
#
# To edit the 'php-fpm' base Image, visit its repository on Github
#    https://github.com/Laradock/php-fpm
#
# To change its version, see the available Tags on the Docker Hub:
#    https://hub.docker.com/r/laradock/php-fpm/tags/
#
# Note: Base Image name format {image-tag}-{php-version}
#

ARG LARADOCK_PHP_VERSION=7.2

# FROM laradock/php-fpm:2.2-${LARADOCK_PHP_VERSION}
FROM letsdockerize/laradock-php-fpm:2.4-${LARADOCK_PHP_VERSION}

LABEL maintainer="Mahmoud Zalt <mahmoud@zalt.me>"

ARG LARADOCK_PHP_VERSION

# Set Environment Variables
ENV DEBIAN_FRONTEND noninteractive

# always run apt update when start and after add new source list, then clean up at end.
RUN set -xe; \
    apt-get update -yqq && \
    pecl channel-update pecl.php.net && \
    apt-get install -yqq \
      apt-utils \
      #
      #--------------------------------------------------------------------------
      # Mandatory Software's Installation
      #--------------------------------------------------------------------------
      #
      # Mandatory Software's such as ("mcrypt", "pdo_mysql", "libssl-dev", ....)
      # are installed on the base image 'laradock/php-fpm' image. If you want
      # to add more Software's or remove existing one, you need to edit the
      # base image (https://github.com/Laradock/php-fpm).
      #
      # next lines are here becase there is no auto build on dockerhub see https://github.com/laradock/laradock/pull/1903#issuecomment-463142846
      libzip-dev zip unzip && \
      docker-php-ext-configure zip --with-libzip && \
      # Install the zip extension
      docker-php-ext-install zip && \
      php -m | grep -q 'zip'

#
#--------------------------------------------------------------------------
# Final Touch
#--------------------------------------------------------------------------
#

COPY ./docker/php-fpm/laravel.ini /usr/local/etc/php/conf.d
COPY ./docker/php-fpm/xlaravel.pool.conf /usr/local/etc/php-fpm.d/

USER root

# Clean up
RUN apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
    rm /var/log/lastlog /var/log/faillog

RUN usermod -u 1000 www-data

# Adding the faketime library to the preload file needs to be done last
# otherwise it will preload it for all commands that follow in this file
RUN if [ ${INSTALL_FAKETIME} = true ]; then \
    echo "/usr/lib/x86_64-linux-gnu/faketime/libfaketime.so.1" > /etc/ld.so.preload \
;fi

WORKDIR /var/www

# php.iniをコンテナに配置する
COPY ./docker/php-fpm/php7.2.ini /usr/local/etc/php/php.ini

# Laraveｌプロジェクト入れるためにgitをインストールする
#RUN apt-get install git
RUN apt-get update && apt-get install -y git

# ゴミが残っているとgitのcloneが行えないため消していおく
RUN rm -r html

# ソースコードをコンテナにコピーする
COPY . .

# .envファイルを作成する
#RUN cp .env.example .env

# Laravelを動作させるための準備をする
# composerをインストールしPHPの依存モジュールをインストールする
# 暗号化用のKeyを作成
# /storage/logs/に対してアクセス権を変更する
RUN curl -sS https://getcomposer.org/installer | php && \
    mv composer.phar /usr/local/bin/composer && \
    composer install && \
    php artisan key:generate && \
    chown -R www-data:www-data /var/www

ADD ./docker/php-fpm/startup.sh /opt/startup.sh
RUN sed -i 's/\r//g' /opt/startup.sh
CMD ["/bin/bash", "/opt/startup.sh"]

# 宣言的な意味で実際にポートを開いてる場合ではない
EXPOSE 9000
```

./{プロジェクト名}/docker/php-fpm/startup.sh

```sh
#!/bin/bash

# php-fpm sever lunch
php-fpm
```

# 3. ECRにリポジトリを作成する

リポジトリの作成を行う

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/fc64a000-e14e-ff49-bab7-167e97d60c5d.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/f7589161-2894-c2f5-5085-f6c72ee9e9e4.png)

# 4. Dockerをビルドし、イメージをECRへpushする

AWSCLIでログインを行う

```sh
aws configure --profile guildapp
$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile guildapp )
```

php-fpmコンテナをpushする

```sh
docker build -t {リポジトリ名} -f docker/php-fpm/Dockerfile .
docker build -t {ECRのリポジトリURI}:latest -f docker/php-fpm/Dockerfile .
docker tag {リポジトリ名}:latest {ECRのリポジトリURI}:latest
docker push {ECRのリポジトリURI}:latest
```

nginxコンテナをpushする

```sh
docker build -t {リポジトリ名} -f docker/nginx/Dockerfile .
docker build -t {ECRのリポジトリURI}:latest -f docker/nginx/Dockerfile .
docker tag {リポジトリ名}:latest {ECRのリポジトリURI}:latest
docker push {ECRのリポジトリURI}:latest
```

# 5.Laravel+NuxtプロジェクトをFargateに乗せる

 [参考サイト](https://github.com/aws-samples/amazon-ecs-fargate-aspnetcore/blob/master/README.md) 


## Fargateクラスターの作成

1. AWSでのECSサービスを起動する。
クラスター＞クラスターの作成

2. クラスターテンプレートを「ネットワーキングのみ」を選択肢して「次のステップへ」

3. クラスタに名前を付け、このクラスタ用の新しいVPCの作成を有効にします。CIDRブロックとサブネットをデフォルトのままにして[作成]をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/833c194a-2776-c64c-ed74-9a3c0f37ef2d.png)

4. 正常にクラスターが作成されたことを確認する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/541ece97-30a2-8be1-6a06-5b0d42a5ab7e.png)

## Application Load balancerの作成

1. EC2サービス＞ロードバランサー＞ロードバランサーの作成をクリック
2. Application Load Balancerの作成ボタンをクリック
3. 下記のように設定を行い次の手順へ進む
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/8db5bead-df46-62d1-d2fa-90e99031229f.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/f5c639b4-1a44-8895-76b7-63dfa782e1ac.png)

4. ALB用の新しいセキュリティグループを作成します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/aef53489-bb99-7d80-0fa8-399e0f474470.png)

5. ターゲットグループに名前を付け、残りのパラメータに次のように設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/118bd22e-008e-661f-8468-97e22abfbfab.png)

6. ターゲットタイプは、ECSタスクレベルロードバランシングのIPアドレスとして選択する必要があります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/8f888322-bda6-6ffa-ec58-e4349c26e832.png)

7. 作成完了されたことを確認する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/876824cb-6778-01bd-7e13-fadf59cebed7.png)

## ECS Fargateタスクを作成する

ECSサービス＞タスク定義＞新しいタスク定義の作成
Fargateを選択する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/bc5778bb-cf88-a427-ea33-e4bcd1d150d0.png)

タスクとコンテナの定義

※ECSTaskのIAMロールがない場合は、ロールを作成する必要がある
[Amazon ECS タスク実行 IAM ロール](https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_execution_IAM_role.html)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/39cf4f95-ac62-da6a-12e3-a3d87cf0a4c5.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/3b914528-4e7d-41fb-1a40-eb0ab0c40e72.png)


nginxコンテナの設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/2748225a-85a8-d471-a7b5-1f2391508640.png)

php-fpmコンテナの設定

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/dcf5fce3-a1f0-ced1-ed25-10d65d59d6c0.png)

作成を実施する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/bdb9b622-7183-5396-dd55-9fba2ef0b105.png)

## ECS Fargateサービスを作成する

ECSサービス＞タスク定義＞FargateLaravelNuxtTestTask＞サービスの作成
 

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/71085449-16f3-9da0-35c4-a54c27648180.png)

サービスの設定を行う
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/c1467f00-ed4f-5e40-9ff0-3cee04ec808d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/cb5d2acf-6f2b-a284-9cf9-e41095bb66e9.png)

ネットワーク構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/bd6d8ec7-f61b-2ec5-849c-077653ee9486.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/cdaf6a34-00ca-490e-4fd8-8c1989627112.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/2ece2792-8f49-4de9-f7e5-8fb091d1d2b5.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/501c9f1f-6e12-b7ff-39b1-e39d2d10224a.png)

AutoScalingの設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/b5aa55a8-dde8-659e-e7ad-51fe2eee971a.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/b2d19cb1-85f5-dd64-a174-e28eb8834624.png)

作成する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/248907f3-e383-13d0-001c-ea4f050fea1c.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/e0e4888b-d00d-91ed-8723-b51ac14e3651.png)

## 動作を確認する
作成したロードバランサーのDNSからアクセスする

![image.png](https://qiita-image-store.s3.amazonaws.com/0/305479/5e66ab64-a05b-f6b6-d7ae-389b659e96e4.png)