AWS Copilot で ECS(Fargate) に Express(Node.js) をデプロイする

AWS Copilot を使って ECS(Fargate) に Express(Node.js)をデプロイする方法を紹介します。

前提

AWS CLI, Copilot CLI がインストール・設定済みで
ローカルでの動作確認には Docker Desktop for Mac を使っています。

  • AWS CLI
$ aws --version
aws-cli/2.2.35 Python/3.8.0 Darwin/20.5.0 source/x86_64 prompt/off
  • Copilot CLI
$ copilot --version
copilot version: v1.13.0
  • Docker Engine
$ docker --version
Docker version 20.10.11, build dea9396
  • maOS 11.4

Express の準備

作業ディレクトリを作って TypeScript で Express が動くように設定します。

$ mkdir copilot-express && cd copilot-express

$ npm init -y

$ npm install -D typescript ts-node @types/node @types/express

$ npm install express

$ npx tsc --init

index.ts の作成

$ touch index.ts

作成したindex.tsに Express の起動と / への GET リクエストハンドラーを定義します。

import express from 'express';
import { Request, Response } from 'express';

const app = express();
const port = 3000;

app.get('/', (req: Request, res: Response) => res.send('Express app works!'));

app.listen(port, () => console.info(`Express listening on port ${port}!`));

スクリプトの追加

package.jsonscripts"start": "ts-node index.ts"を追加します。

{
  ~~~
  "scripts": {
    "start": "ts-node index.ts"
  }
  ~~~
}

Dockerfile の作成

$ touch Dockerfile
FROM node:16

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD [ "npm", "start" ]

Docker イメージの作成 & 実行

$ docker build -t copilot-express .

$ docker images | grep copilot-express

$ docker run -p 3000:3000 -d copilot-express

http://localhost:3000 にアクセスして Express app works! が表示されたら準備完了です。

f:id:morugu:20220106175408p:plain

Copilot を構成する要素

デプロイする前に Copilot について紹介します。

Copilot には Service, Environment, Application という 3 つの中心となる要素があります。

f:id:morugu:20220106170948p:plain
Copilot の中心となる3つの要素

Service はコンテナで実行されるアプリケーションで
今回は api という名前で Service を作成します。

Environment は test, staging, production などの環境で
今回は test という名前で Environment を作成します。

Application は Service, Environment をまとめた概念で
今回は copilot-express という名前で Application を作成します。

今回デプロイするアプリケーションは Service, Environment, Application 全て 1 つずつの構成になります。

aws.github.io

Copilot で ECS(Fargate) にデプロイ

copilot initの実行

copilot initを実行して、Copilot の初期化 & デプロイを行います。 いくつか質問が表示されるので回答します。

Application 名を聞かれるのでcopilot-expressと入力します。
$ copilot init

Note: It's best to run this command in the root of your Git repository.
Welcome to the Copilot CLI! We're going to walk you through some questions
to help you get set up with a containerized application on AWS. An application is a collection of
containerized services that operate together.

What would you like to name your application? [? for help] copilot-express
ワークロードタイプを聞かれるのでLoad Balanced Web Serviceを選択します。
Which workload type best represents your architecture?  [Use arrows to move, type to filter, ? for more help]
  Request-Driven Web Service  (App Runner)
> Load Balanced Web Service   (Internet to ECS on Fargate)
  Backend Service             (ECS on Fargate)
  Worker Service              (Events to SQS to ECS on Fargate)
  Scheduled Job               (Scheduled event to State Machine to Fargate)
Service 名を聞かれるので api と入力します。
What do you want to name this service? [? for help] api
どの Dockerfile を使うか聞かれるので ./Dockerfile を選択します。
Which Dockerfile would you like to use for api?  [Use arrows to move, type to filter, ? for more help]
  > ./Dockerfile
    Enter custom path for your Dockerfile
    Use an existing image instead
今回は test 環境へのデプロイなので y を入力します。
All right, you're all set for local development.

Would you like to deploy a test environment? [? for help] (y/N) y

質問への回答が終わると IAM Role, Subnet, VPC などの環境構築が開始されるのでしばらく待ちます。

環境構築が終わったら ECR に Docker イメージがプッシュされ、ECS へのデプロイが始まります。

✔ Linked account AWS_ACCOUNT_ID and region ap-northeast-1 to application copilot-express..

✔ Proposing infrastructure changes for the copilot-express-test environment.

✔ Created environment test in region ap-northeast-1 under application copilot-express.

✔ Deployed service api.
Recommended follow-up action:
  - You can access your service at http://xxxxx.ap-northeast-1.elb.amazonaws.com over the internet.

表示された URL にアクセスしてローカルと同様に Express app works! が表示されたらデプロイ完了です!

Application の削除

動作確認や実際に ECS にデプロイされている状態が確認できたら
今回作成した Application を削除します。

$ copilot app delete

まとめ

Copilot の概念(Beanstalk と似ている)と手順を覚えてしまえば、コンテナを ECS にデプロイする良い手段だと感じました!

実際の運用では Copilot での CI/CD や Sidecar pattern なども入ってくるので、その辺りも試してみようと思います。