目次

はじめに

Next.jsで作成したアプリケーションをAWS ECSにデプロイさせていきます。
でいる限り、コマンドライン上で操作できるように調べながらやっていきたいと思います。

Next.js アプリケーションの準備

まず、Next.jsアプリケーションを作成します。
「npx create」コマンド実行時に聞かれる質問は基本デフォルトでOK。

npx create-next-app@latest my-nextjs-app
cd my-nextjs-app
npm run build


Dockerコンテナの作成

1.Dockerfileの作成

次に、Next.jsアプリケーション用のDockerfileを作成します。

C:.
│  .gitignore
│  Dockerfile ←新規作成
│  next-env.d.ts
│  next.config.mjs
│  package-lock.json
│  package.json
│  README.md
│  tsconfig.json
├─.next
├─node_modules
├─public
└─src

ファイル中身
FROM node:14-alpine
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
FROM ベースとなるコンテナイメージを指定している
WORKDIR コンテナ内で作業するディレクトリを指定している
COPY ホストマシンからコンテナ内にファイルをコピーしている
EXPOSE コンテナが使用するポートを指定している
ENTRYPOINT コンテナが起動する際に実行されるコマンドを指定します。この場合は、npm startが実行される

2. Dockerイメージのビルドとコンテナの起動

Dockerイメージをビルドし、Next.jsアプリケーションをDockerコンテナ内で実行します。

docker build -t my-nextjs-app .
docker run -d -p 3000:3000 --name my-nextjs-container my-nextjs-app

3. ブラウザでアクセス

ブラウザで以下のURLにアクセスすると、Next.jsアプリケーションが表示されます。

http://localhost:3000

Amazon ECR リポジトリの作成(オプション)

AWS Management ConsoleでECRリポジトリを作成します。コマンドラインから作成する場合:

aws ecr create-repository --repository-name ${REPOSITORY_NAME}
aws ecr create-repository --repository-name my-repo

Dockerイメージのプッシュ

Amazon ECR レジストリに対して Docker を認証する

get-loginコマンドは非推奨になったみたいです。

aws ecr get-login-password | docker login --username AWS --password-stdin 0xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo

–password-stdin パスワードを標準入力から読み取る

{0xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo}の部分は先ほど作成した、repositoryUri


DockerイメージをECRにプッシュします。

リポジトリにイメージをプッシュできるように、イメージにタグを付けます。

docker tag my-repo:latest 0xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:latest

新しく作成した AWS リポジトリにこのイメージをプッシュ

docker push 0xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:latest

VPCとパブリックサブネットの作成

VPCの作成

aws ec2 create-vpc --cidr-block 10.1.0.0/16 --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=MyVPCForECS}]'

インターネットゲートウェイの作成とアタッチ

インターネットゲートウェイの作成

aws ec2 create-internet-gateway --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=MyInternetGatewayForECS}]'

作成されたインターネットゲートウェイのIDを取得

IGW_ID=$(aws ec2 describe-internet-gateways --query 'InternetGateways[?Attachments[0].VpcId==`null`].InternetGatewayId' --output text)

インターネットゲートウェイをVPCにアタッチ

{VPC_ID}のところは、先ほど作成したVpcIdに置き換える

aws ec2 attach-internet-gateway --vpc-id {VPC_ID} --internet-gateway-id $IGW_ID

パブリックサブネットの作成

aws ec2 create-subnet --vpc-id <VPC_ID> --cidr-block 10.1.1.0/24 --availability-zone <Your_AZ> --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=MyPublicSubnet}]'

ルートテーブルの作成とルート追加

ルートテーブルの作成

aws ec2 create-route-table --vpc-id <VPC_ID> --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=MyRouteTable}]'

作成されたルートテーブルのIDを取得

ROUTE_TABLE_ID=$(aws ec2 describe-route-tables --filters "Name=vpc-id,Values=<VPC_ID>" "Name=association.main,Values=false" --query 'RouteTables[0].RouteTableId' --output text)

ルートテーブルにインターネットゲートウェイへのルートを追加

aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID

ルートテーブルをサブネットにアソシエート

aws ec2 associate-route-table --subnet-id <SUBNET_ID> --route-table-id $ROUTE_TABLE_ID

セキュリティグループの作成

aws ec2 create-security-group --group-name MySecurityGroup --description "My security group" --vpc-id {VPC-ID}

セキュリティグループの設定

  # インバウンドルールを追加 (例: HTTPアクセス許可)
# my-ipはコマンドラインで「curl -s http://checkip.amazonaws.com/」を実行するとipアドレス分かります
aws ec2 authorize-security-group-ingress --group-id {Your-Security-Group-ID} --protocol tcp --port 3000 --cidr {my-ip}/32

AWS ECS クラスターの作成

aws ecs create-cluster --cluster-name MyCluster

タスク定義の作成

タスク定義にはDockerイメージ、メモリ、CPU、ネットワーク設定などを指定します。JSON形式で設定し、ECS Management ConsoleやCLIを使用して登録します。

aws ecs register-task-definition --cli-input-json file://taskdef.json(以下のタスク定義ファイルパス)

タスク定義ファイル(taskdef.json):

{
        "family": "my-task-def",
        "networkMode": "awsvpc",
        "containerDefinitions": [
          {
            "name": "my-app",
            "image": "0xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/my-repo:latest",
            "essential": true,
            "memory": 512,
            "cpu": 256,
            "portMappings": [
              {
                "containerPort": 3000,
                "hostPort": 3000
              }
            ]
          }
        ],
        "requiresCompatibilities": ["FARGATE"],
        "executionRoleArn": "arn:aws:iam::0xxxxxxxxx:role/ecsTaskExecutionRole",
        "cpu": "256",
        "memory": "512"
      }

サービスの作成

ECSサービスはタスクを実行し、スケーリングを管理します。サービスを作成し、クラスター、タスク定義、デプロイメントオプション(例: ロードバランサーの設定)を指定します。

[subnet-xxxxx]と[sg-xxxxxx]は、「VPCとパブリックサブネットの作成」で作成したvpc-id、subnet-idに置き換える

 aws ecs create-service --cluster MyCluster --service-name my-service --task-definition my-task-def --desired-count 1 --network-configuration "awsvpcConfiguration={subnets=[subnet-xxxxx],securityGroups=[sg-xxxxxx],assignPublicIp=ENABLED}" --launch-type FARGATE

動作確認

AWSコンソールにアクセスし、作成したタスクの詳細ページを開き、「パブリックIPのオープンアドレス」を確認する。
ブラウザで、「確認したipアドレス:3000」にアクセスする。


おわりに

一旦、ECSにデプロイできました。
本当は、スケーリングの設定や障害復旧の確認までしたいのですが、今回はここまでにします。