0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDKでNext.jsをデプロイする【第2回】〜ECS Task Definition作成〜

0
Last updated at Posted at 2026-02-27

はじめに

前回、ECRリポジトリを作成し、Next.jsアプリのDockerイメージをpushしました。
第2回となる本記事では、ECSのタスク定義(Task Definition)を作成します。

本シリーズの構成

1. ECR編

2. ECS Task Definition編(本記事)
3. ALB編
4. ECS Service編
5. セキュリティ編

構成全体と今回の作業範囲

AWS全体構成の中で本記事がどの範囲を扱うのかを確認します。

今回のゴール

  • ECS Clusterを作成する
  • Fargate用Task Definitionを作成する
  • ECRのDockerイメージを指定する
  • CloudWatch Logsへのログ出力設定を行う
  • ポート設定を行う

ECS Task Definitionとは?

ECSでコンテナを動かすための「設計図」です。

Task Definitionには、

  • 使用するコンテナイメージ
  • CPUやメモリの割り当て
  • ポート番号
  • 環境変数
  • ログ出力先

などを定義します。

この定義は、ECS Serviceがタスクを起動する際に参照されます。

2-1. ECS Clusterを作成する

まずは、ECSを動かすための「入れ物」となるClusterを作成します。

CDKプロジェクト内に"lib/ecs-stack.ts"を作成します。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';

export class EcsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPC(デフォルトVPCを使用)
    const vpc = ec2.Vpc.fromLookup(this, 'DefaultVpc', {
      isDefault: true,
    });

    // ECS Cluster
    const cluster = new ecs.Cluster(this, 'Cluster', {
      vpc,
    });
  }
}

ECS Clusterは「入れ物」で、この段階ではまだ使いません。ECS Serviceを作成して初めて、Cluster上でタスク(コンテナ)が起動します(本記事の時点ではコンテナは起動しません)。

また今回は検証のためデフォルトVPCを使用します。デフォルトVPCが存在しない環境ではエラーになります。本番運用では専用VPC(Public/Private Subnetを分ける等)を用意する構成が一般的です。

2-2. Fargate用のTask Definitionを作成する

次に、Fargate用のTask Definitionを作成します。

以下のコードを、lib/ecs-stack.ts内のEcsStack constructorの中に追加します。

const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {
  cpu: 256,
  memoryLimitMiB: 512,
});

FargateTaskDefinitionでは、ECRからのイメージ取得やCloudWatch Logsへのログ出力に必要な実行ロール(Execution Role)はCDKが自動作成します。
そのため、明示的にIAMロールを定義しなくても動作します。

この定義は、ECS Serviceがタスクを起動する際に参照されます。
また、Task Definitionは変更するたびに新しいリビジョンが作成されます。

CPUとメモリについて
cpu: 256 → 0.25 vCPU
memoryLimitMiB: 512 → 512MB
今回は検証用の最小構成です。

FargateではCPUとメモリの組み合わせに制約があります。値を変更する場合は公式ドキュメントを確認してください。

Fargateとは?

Fargateは、サーバー(EC2インスタンス)を自分で用意・管理しなくてもコンテナを実行できるAWSの仕組みです。
通常のECSでは、コンテナを動かすためのEC2インスタンスを用意する必要がありますが、Fargateを使うとその管理をAWSが代わりに行ってくれます。
そのため、インフラ管理の負担を減らし、コンテナの実行に集中できます。

2-3. ECRイメージを指定する

lib/ecs-stack.ts先頭にimportを追加します。

import * as ecr from 'aws-cdk-lib/aws-ecr';

以降の手順では、基本的にEcsStackのconstructor内にコードを追加してください。

リポジトリの定義を追加します。

const repository = ecr.Repository.fromRepositoryName(
  this,
  'ImportedRepository',
  'my-nextjs-app'
);

'my-nextjs-app' は ECRリポジトリ名です。
前回作った名前と一致してないと後続のタスク起動時にイメージ取得で失敗します。

2-4. コンテナ定義とログ出力設定を追加する

lib/ecs-stack.ts先頭にimportを追加します。

import * as logs from 'aws-cdk-lib/aws-logs';

Task Definitionにコンテナを追加します。

const container = taskDefinition.addContainer('Container', {
  // ECRリポジトリからイメージを指定
  // ※本番は固定タグ推奨
  image: ecs.ContainerImage.fromEcrRepository(repository),
  // CloudWatch Logsへログを出力する設定
  logging: ecs.LogDrivers.awsLogs({
    streamPrefix: 'nextjs',
    logRetention: logs.RetentionDays.ONE_WEEK,
  }),
});

fromEcrRepository(repository) のようにタグを省略した場合、デフォルトでlatestタグが参照されます。
latestは上書き可能なタグのため、本番環境では再現性が担保できません。
本番では固定バージョンタグを明示的に指定することを推奨します。

CloudWatch Logs設定について

logging: ecs.LogDrivers.awsLogs({
  streamPrefix: 'nextjs',
  logRetention: logs.RetentionDays.ONE_WEEK,
}),

awsLogsを指定すると、CloudWatch Logs用のLogGroupはCDKによって自動生成されます。

  • streamPrefixはログストリーム名の接頭辞になります。
  • logRetentionはログの保持期間を指定する設定です。

この設定により、ECSコンテナの標準出力(console.logなど)および標準エラー出力がCloudWatch Logsへ自動送信されます。

この段階ではまだタスクは起動していないため、CloudWatch Logsにはログは出力されません。実際のログ確認はECS Service作成後に行います。

2-5. ポート設定を行う

コンテナが待ち受けるポートをECSに伝える設定です。
※これはコンテナ内部ポートの指定であり、外部公開は次回のALBおよびService設定で行います。

container.addPortMappings({
  containerPort: 3000,
});

これで、Task Definitionの設定が完了しました。

2-6. bin側でStackを追加する

bin 配下のファイルにStackを追加します。

import { EcsStack } from '../lib/ecs-stack';
//...
new EcsStack(app, 'NextjsInfraEcsStack', { env });

2-7. デプロイする

cdk deployを実行すると、CloudFormationを通じてECS ClusterとTask Definitionが作成されます。

cdk deploy NextjsInfraEcsStack --profile <プロファイル名>

デプロイが正常に完了すると、以下のログが表示されます。

✅  NextjsInfraEcsStack

✨  Deployment time: xx.xx s

本記事で作成したスタックに含まれるAWSリソースは、削除するまで料金が発生します。
検証が不要になった場合は、以下のコマンドでスタックを削除してください。

cdk destroy <スタック名> --profile <プロファイル名>

AWSコンソールで確認

① ECS → クラスター

  • クラスターが作成されているか
    クラスター名(参考): NextjsInfraEcsStack-NextjsClusterXXXXXXXX-XXXXXXXX

② ECS → タスク定義

  • タスク定義が登録されているか
  • ステータスがACTIVEになっているか
    タスク定義名(参考):NextjsInfraEcsStackNextjsTaskDefXXXX

③ CloudFormation → スタック

  • NextjsInfraEcsStackのステータスが CREATE_COMPLETE または UPDATE_COMPLETE になっているか

ここまで確認できれば、基盤構築は完了です。
なお、まだECS Serviceを作成していないため、コンテナは起動していません。

最終コード(今回追加・修正したファイル)

lib/ecs-stack.ts

コード全体
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as logs from 'aws-cdk-lib/aws-logs';

export class EcsStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // VPC(デフォルトVPCを使用)
    const vpc = ec2.Vpc.fromLookup(this, 'DefaultVpc', {
      isDefault: true,
    });

    // ECS Cluster
    const cluster = new ecs.Cluster(this, 'Cluster', {
      vpc,
    });

    const taskDefinition = new ecs.FargateTaskDefinition(this, 'TaskDefinition', {
      cpu: 256,
      memoryLimitMiB: 512,
    });

    const repository = ecr.Repository.fromRepositoryName(
      this,
      'ImportedRepository',
      'my-nextjs-app'
    );

    const container = taskDefinition.addContainer('Container', {
      // ECRリポジトリからイメージを指定
      // ※本番は固定タグ推奨
      image: ecs.ContainerImage.fromEcrRepository(repository),
      // CloudWatch Logsへログを出力する設定
      logging: ecs.LogDrivers.awsLogs({
        streamPrefix: 'nextjs',
        logRetention: logs.RetentionDays.ONE_WEEK,
      }),
    });

    container.addPortMappings({
      containerPort: 3000,
    });
  }
}

bin/cdk-nextjs-infra.ts

コード全体
#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { EcrStack } from '../lib/ecr-stack';
import { EcsStack } from '../lib/ecs-stack';

const app = new cdk.App();

const env = {
  account: process.env.CDK_DEFAULT_ACCOUNT,
  region: process.env.CDK_DEFAULT_REGION,
};

new EcrStack(app, 'NextjsInfraEcrStack', { env });

new EcsStack(app, 'NextjsInfraEcsStack', { env });

ここまでの成果

ECSでコンテナを起動するためのTask Definitionが完成しました。

次回

次回は、ALB(Application Load Balancer)を作成し、ECSへ外部からアクセスできるように設定します。

→ 第3回:ALB編はこちら

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?