7839

雑草魂エンジニアブログ

【AWS】Next.js(SSR) を AWS(ECR + ECS + Fargate) にデプロイしてみた

Next.js(SSR)のアプリケーションを作成して、AWS にデプロイしてみたので、備忘録として残しておく。

今回の構成はこのようになっている。

f:id:serip39:20200903211401p:plain

aws.amazon.com

バージョン情報は以下の通りである。

  • aws
  • docker
    • Docker version 19.03.12, build 48a66213fe

0. ECR にイメージリポジトリを作成する

今回は、AWS Web Console でリポジトリを作成した。もちろん、AWS-CLI からも作成は可能である。

docs.aws.amazon.com

イメージリポジトリを作成後、イメージリポジトリURI をメモして、控えておく。

1. アプリをコマンドで実行できることを確認する

開発時は、 yarn dev で開発用のサーバーを起動して、開発を行っていたかと思う。本番は、yarn build してから、yarn start で本番環境で Nodeサーバーを起動する。

<--省略-->
"scripts": {
  "dev": "nodemon",
  "build": "next build && tsc --project tsconfig.server.json",
  "start": "NODE_ENV=production node dist/index.js"
},
<--省略-->

docker image を作成する前に、ローカル環境で、yarn buildyarn start が問題なく実行できることを確認する。実行して、エラーが出なければ、基本的には大丈夫である。

2. docker imageを作成する

Dockerfile.dockerignore をアプリケーションディレクトリ直下に配置する。

app  
 ┝ pages  
 ┝ (省略)
 ┝ package.json  
 ┝  .dockerignore  ← ここに追加する
 └ Dockfile  ← ここに追加する

Dockfile では Node 環境を用意し、必要なパッケージをインスール、ビルド後に、本番環境を起動するコマンドを実行している。(コンテナ内では、3000ポートで起動するように設定している。)

FROM node:14-alpine
RUN mkdir -p /app
COPY . /app
WORKDIR /app
RUN apk --update add tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    apk del tzdata && \
    apk add --no-cache bash
RUN yarn install && \
    yarn build
ENV HOST 0.0.0.0
EXPOSE 3000
CMD ["yarn", "start"]

docker imageに含める必要のないファイルを .dockerignore に列挙しておく。

node_modules/
.next/
dist/

上記の Dockerfile と .dockerignore に従い、docker build コマンドで docker image を作成する。(-t で、'名前:タグ' を設定する。)名前については、わかりやすいように私は、ECR で設定した<repositry-name>としている。

$ docker build -t <repositry-name>:latest .

build — Docker-docs-ja 17.06 ドキュメント

完成した docker image をローカル環境で実際に動作確認を行う。

// imageの確認
$ docker images
// Dockerコンテナを起動する
$ docker run -d -p 3000:3000 --name <repositry-name> <repositry-name>:latest

Docker run リファレンス — Docker-docs-ja 17.06 ドキュメント

http://localhost:3000 にアプリケーションが問題なく起動していれば、問題ない。

3. ECRにdocker imageをpushする

imageへのタグ付け(バージョニング)を行う。

$ docker tag <repositry-name>:latest <-repository URI ->/<repositry-name>:latest

ECRへのpush権限をdockerに与えるために AWS コマンドを実行する。AWS CLIの認証情報に関して、profile を用いている。profileに関しては、こちら を参考にしてください。

$ aws ecr get-login-password --profile <-profile name-> | docker login --username AWS --password-stdin <-repository URI ->/<repositry-name>:latest

image を ECR へ push する。

$ docker push <-repository URI ->/<repositry-name>:latest

4. Fargateクラスターを作成する

次に、AWS Web Console にて、ECS を選択して、クラスターを作成していく。

f:id:serip39:20200903223542j:plain

customを選択する。

f:id:serip39:20200903224203j:plain

  • コンテナ名:任意に設定して問題ないが、私は ECR のリポジトリ名と同じで設定した。
  • イメージ:ECR のリポジトリURI を設定する。
  • ポートマッピング:「3000」とする。Dockerfile で 3000 ポートで設定しているので、ここが 3000 となる。

その他の設定は、今後すべきであるが、現段階ではとりあえず初期設定のままとした。

f:id:serip39:20200903224923j:plain

サービスを定義するでは、「ロードバランサーの種類」を「Application Load Balancer(ALB)」とする。ALB とせずに、自分で設定をしてもいいのであるが、ここで ALB を選択することで AWS 側で自動で様々な設定を行ってくれるので、今回は ALB を選択する。

f:id:serip39:20200903225231j:plain

クラスターの設定では、「クラスター名」を決定する。「コンテナ名-cluster」などで問題ないと思われる。

これで設定は完了である。

「作成実行」を行う。全てが完了になるまで、数分かかるので待機する。

5. ALBのリスナーを「80」に設定する

クラスター > 今回作成したクラスター > サービス を選択して、ロードバランシングのターゲットグループ名から、「EC2」の画面に移動する。

f:id:serip39:20200903230100j:plain

EC2 の ロードバランシング > ロードバランサーDNS名などを確認することができる。

f:id:serip39:20200903231500j:plain

現時点では、DNS名:3000 ポートにアクセスすることで問題なく、アプリケーションを確認することができる。

ただし、毎回 3000 ポートを指定するのは面倒なので、「リスナー」タブより、外部に公開するポートは、「3000」ではなく、「80」に変更する。(SSH対応をする場合は、別途設定が必要である。)

まとめ

今回は、Next.js を AWS にデプロイした方法を整理した。

www.docker.com

2020/07に、AWS と Docker のコラボレーションにより、Docker の ECSインテグレーションが発表されたので、今後は ECR に PUSH せずに、DockerHub に PUSH することも増えるかもしれない。この機能を試すのも、今後楽しみである。

それでは、ステキな開発ライフを。