🚲

CDKでFargateを構築してみる with TypeScript

2022/03/26に公開

最近、AWS の勉強を始めました。はじめはコンソールでぽちぽちしてたんですが、自分がした作業をふりかえりやすいので、CDK を使うようになりました。

今回は、CDK を使って Fargate でサンプルアプリを動作させてみます。言語は TypeScript です。

今回書いたコードは下記に置いてあります。

https://github.com/hirokisakabe/fargate-cdk-sample

AWS CDK のセットアップ

下記を参考に進めます。

https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html

下記を参考に、AWS アカウントを作っておきます。

https://docs.aws.amazon.com/cli/latest/userguide/getting-started-prereqs.html

ローカルマシンに AWS CLI と CDK をインストールします。

$ brew install awscli aws-cdk

下記を参考に、AWS CLI に AWS アカウントを紐づけます。

https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html

$ aws configure

CDK を初期化します。

$ cdk bootstrap aws://<AWSアカウントID>/<リージョン>

CDK プロジェクトを初期化します。今回は TypeScript を使います。

$ cdk init app --language typescript
$ ls
bin/
lib/
node_modules/
test/
README.md
cdk.json
jest.config.js
package-lock.json
package.json
tsconfig.json

必要なファイルが一通り生成されました。

Docker イメージの準備

動作させる Docker イメージを準備します。

今回は、下記の Node.js のサンプルページに従って進めます。

https://nodejs.org/ja/docs/guides/nodejs-docker-webapp/

ポートだけ、サンプルページと違って、80 に変更しています。

後ほど package-lock.json を生成する必要があるので、Node.js をインストールします。

$ brew install node@14

今回は、CDK のリポジトリに app/ ディレクトリを作って、そこにコードを置くことにします。

$ mkdir app
$ cd app

サンプルページに沿ってファイルを準備します。

package.json
{
  "name": "docker_web_app",
  "version": "1.0.0",
  "description": "Node.js on Docker",
  "author": "First Last <first.last@example.com>",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "dependencies": {
    "express": "^4.16.1"
  }
}
server.js
"use strict";

const express = require("express");

const PORT = 80;
const HOST = "0.0.0.0";

const app = express();
app.get("/", (req, res) => {
  res.send("Hello World");
});

app.listen(PORT, HOST);
console.log(`Running on http://${HOST}:${PORT}`);
Dockerfile
FROM node:12

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 80
CMD [ "node", "server.js" ]
dockerignore
node_modules
npm-debug.log

package-lock.json を生成します。

$ npm install

Docker イメージをビルドします。

$ docker build . -t node-web-app

一度動かしてみます。

$ docker run -p 80:80 -d node-web-app

ローカルで動作することを確認できました 🎉

ECR へ Docker イメージを push

下記を参考に進めます。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/docker-push-ecr-image.html

ECR に対して Docker クライアントを認証します。

$ aws ecr get-login-password --region <リージョン> | docker login --username AWS --password-stdin <AWSアカウントID>.dkr.ecr.<リージョン>.amazonaws.com

ECR リポジトリを作ります。
今回は、sample-node-web-app という名前で作りました。

$ aws ecr create-repository \
    --repository-name sample-node-web-app \
    --image-scanning-configuration scanOnPush=true \
    --region <リージョン>

IMAGE ID を確認します。

$ docker image ls
REPOSITORY          TAG             IMAGE ID       CREATED          SIZE
node-web-app        latest          75ed3927be19   7 minutes ago    920MB

イメージに ECR 用のタグをつけます。

$ docker tag 75ed3927be19 <AWSアカウントID>.dkr.ecr.<リージョン>.amazonaws.com/sample-node-web-app:latest

イメージを push します。

$ docker push <AWSアカウントID>.dkr.ecr.region.amazonaws.com/sample-node-web-app:latest

CDK で Fargate を構築する

いよいよ本題です。

lib/fargate-cdk-sample-stack.ts を書き換えていきます。

下記を参考にしています。

https://github.com/aws-samples/aws-cdk-examples/tree/master/typescript/ecs/fargate-application-load-balanced-service

lib/fargate-cdk-sample-stack.ts
import { Stack, StackProps } from "aws-cdk-lib";
import { Construct } from "constructs";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import * as ecr from "aws-cdk-lib/aws-ecr";
import * as ecs from "aws-cdk-lib/aws-ecs";
import * as ecs_patterns from "aws-cdk-lib/aws-ecs-patterns";

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

    const vpc = new ec2.Vpc(this, "MyVpc", { maxAzs: 2 });
    const cluster = new ecs.Cluster(this, "Cluster", { vpc });

    const repository = ecr.Repository.fromRepositoryName(
      this,
      "SampleRepository",
      "sample-node-web-app"  // 先ほど作ったリポジトリ名
    );

    new ecs_patterns.ApplicationLoadBalancedFargateService(
      this,
      "FargateService",
      {
        cluster,
        taskImageOptions: {
          image: ecs.ContainerImage.fromEcrRepository(repository),
        },
      }
    );
  }
}

デプロイします。

$ cdk synth
$ cdk deploy

cdk deployで最後の方にコンソールに出力されている URL にアクセスしてみます。

無事、デプロイできました 🎉

あとがき

Web コンソールでぽちぽちやってるときより、楽しいと感じました。

このあたりが楽しかったのかな、とふりかえってます。

  • 一応 TypeScript のコードを書くことになること
  • デプロイするときのバーが進む感じが何となくカッコイイ

楽しさは大事ですね。

Discussion