
クラウド上でアプリケーションをDockerイメージとして管理し、Dockerコンテナとして運用する方法として、AWSのECRとECSがあります。今回はECRとECSの入門として、ReactのDockerアプリケーションをAWS上で稼働させる方法を紹介します。
見出し
はじめに
アプリケーションをDocker化するのが主流となっている昨今において、Dockerイメージの管理やDockerコンテナの運用をクラウド上で完結させることが求められています。AWSではそのためのサービスとして、Dockerイメージ管理のためのECR、Dockerコンテナ運用のためのECSが提供されています。
今回はReactのDockerアプリケーションを対象として、AWSのECRとECSを使って、AWS上でDockerコンテナを稼働させてみましょう。
前提
以下の準備が完了している必要があります。
- NodeJSがインストールされていること
- Dockerがインストールされていること
- AWS CLIがインストールされ、適切なIAMのユーザが作成済みで、プロファイルに設定されていること(AWS CLIでECSをすべて操作するにはIAMのユーザ「AmazonEC2ContainerServiceFullAccess」のロールを割り当てる必要があります)
- AWS上にテスト用のVPCとパブリックなサブネットが構築済みであること(今回はデフォルトをそのまま使います)
- AWS上にテスト用のセキュリティグループが構築済みであること(今回はデフォルトのセキュリティグループに、自分のIP向けにSSHポート22、HTTPポート80、TCPポート「32768–61000」を公開する設定を追加したものを使います)
- AWSのEC2インスタンスにSSHするためのキーペアが作成済みであること(今回は「MyKeyPair」という名前で作成したものを使います)
上記のAWSの設定の意味が理解できない場合は、この記事の内容に取り組む前にIAM、EC2、VPC、AWS CLIの基礎を学んだ方が良いでしょう。
細かいバージョンは「環境」を参照してください。
ECRとは?
ECR(Elastic Container Registry)とは、AWSが提供しているDocker向けのレジストリーサービスです。Dockerのレジストリーサービスと言えばDocker社が提供しているDockerHubですが、そのAWS版です。詳しい説明は公式ドキュメントを参照してください。
ECSとは?
ECS(Elastic Container Service)とは、AWSが提供しているDocker向けのコンテナオーケストレーションサービスです。簡単に言えばAWS上でDockerコンテナを稼働させる環境と、そのコンテナをスケールするための機能が主に提供されています。使用イメージとしては、開発したDockerアプリケーションをビルドしてイメージにし、そのイメージをECRにPushして管理し、そのイメージを使ってECSでDockerコンテナを起動して運用するような感じになります。こちらも詳しくは公式ドキュメントを参照してください。
ReactのDockerアプリケーションの作成
今回の主題ではありませんが、ECRとECSを使うためにDockerアプリケーションが必要なのでReactで簡単に作成します。
ベースを作る
create-react-appでReactのサンプルアプリケーションを作り、Docker化しましょう。
$ create-react-app sample-react-ecs-app
$ cd sample-react-ecs-app/
$ touch Dockerfile
$ tree -I node_modules
.
├── Dockerfile
├── README.md
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ └── serviceWorker.js
└── yarn.lock
Dockerファイルの作成
ReactアプリケーションをNginxに乗せる構成にしましょう。
Dockerfile
Dockerfileは以下のようにします。
FROM node:11-alpine as builder
WORKDIR /app
COPY package.json .
COPY yarn.lock .
RUN yarn install
COPY . .
RUN yarn build
FROM nginx:1.15-alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
完成です。
サンプルアプリケーションの起動
完成したサンプルアプリケーションを起動してみましょう。
$ docker image build -t sample-react-ecs-app:latest .
$ docker images | grep sample-react-ecs-app
sample-react-ecs-app latest 1416916c000b 17 seconds ago 18.2MB
$ docker container run --rm -p 80:80 sample-react-ecs-app:latest
起動した状態でブラウザで「localhost:80」を開きます。
OKですね。
ECRのリポジトリ作成とDockerイメージの管理
それではAWSのECRでDockerリポジトリを作っていきましょう。
ECRでリポジトリを作成する
AWSコンソールにログインし、「ECS」をクリックします。
「Repositories」を選択し、「Get started」をクリックします。
「Repository name」に任意のリポジトリ名(今回は「sample-react-ecs-app」)を入力し、「Next step」をクリックします。
「Done」をクリックして完了です。
新しいリポジトリが作成されました。
DockerイメージをECRにPushする
リポジトリ画面の「View Push Commands」をクリックます。
すると以下のようにPushする手順が出てきます。
それでは、この手順通りにPushしてみましょう。(すでにDockerイメージはビルド済みですが、手順通りにビルドもしています)
$ $(aws ecr get-login --no-include-email --region us-east-1)
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
$ docker build -t sample-react-ecs-app .
$ docker tag sample-react-ecs-app:latest XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/sample-react-ecs-app:latest
$ docker push XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/sample-react-ecs-app:latest
The push refers to repository [XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/sample-react-ecs-app]
61b57277474b: Pushed
7f875a1274be: Pushed
42538a727f9c: Pushed
5abab21bd32e: Pushed
df64d3292fd6: Pushed
latest: digest: sha256:b6477ba3dfc6932f2d4ce911fe5b53033b31dbe57254ecb057634b9500a232a2 size: 1363
画面を確認してみましょう。
ECRにDockerイメージがPushされていることが確認できました。
ECSによるDockerコンテナの運用
次にDockerイメージをECSで稼働させましょう。
ECSクラスターの作成
「Clusters」を選択し、「Create Cluster」をクリックします。
「EC2 Linux + Networking」を選択し、「Next step」をクリックします。
今回はクラスターに前半に以下を設定します。
- Cluster name: 「sample-react-ecs-app-cluster」
- Provisioning Model: On-Demand Instance
- EC2 Instance type: t2.micro
- Number of Instance: 2 (今回は2つのEC2を使います)
- Key pair: MyKeyPair
クラスターの後半には以下を設定します。
- VPC: 今回のテスト用に準備したVPC
- Subnet: 今回のテスト用に準備したパブリックなサブネットを2つ
- Security group: 今回のテスト用に準備したセキュリティグループ
- Container Instance IAM role: ecsInstanceRole (自動で作成される)
「Create」をクリックします。
すると以下のようにクラスターが作成されます。作成が完了したら「View Cluster」をクリックします。
「Registered container instances」が「2」になり、「ECS Instances」のタグをクリックすると2つのインスタンスが「ACTIVE」になっていることが確認できます。
また、「EC2 Dashboard」を見ると、EC2インスタンスが自動的に2つ起動しています。
これでクラスターの作成が完了しました。
ECSタスクの作成
「Task Definitions」を選択し、「Create new Task Definition」をクリックします。
「EC2」を選択し、「Next step」をクリックします。
「Configure task and container definitions」の前半に以下を設定します。
- Task Definition Name: 「sample-react-ecs-app-task」
- Network Mode: Bridge
「Container Definition」の「Add container」をクリックしてコンテナ情報を設定します。
コンテナ情報には以下を設定します。
- Container name: sample-react-ecs-app
- Image: (ECRに作成したリポジトリの「Repository URI」)
- Memory Limits: Hard limit, 128
- Port mappings: 0:80 (Host portを「0」にすると動的ポートマッピング(dynamic host port mapping)が有効になり、同一インスタンス内に複数のDockerコンテナを起動できる)
入力が終わったら「Add」をクリックします。
コンテナ情報が追加できたので、「Create」をクリックします。
タスクの作成が完了しました。
ECSタスクの実行
ECSのタスクとは、Dockerコンテナの起動コマンドです。
「Action」から「Run Task」をクリックします。
以下を設定して、「Run Task」をクリックします。
- Launch type: EC2
- Cluster: sample-react-ecs-app-cluster
- Number of tasks: 2 (Dockerコンテナの数を2つにする)
- Placement: AZ Balanced Spread
「Tasks」タブを選ぶと、2つのタスクが実行されています。
タスクの「Last status」が「PENDING」から「RUNNING」になればDockerコンテナの起動が完了しています。
試しに、1つのインスタンス内のDockerコンテナでの状況を確認してみましょう。
「EC2 Dashboard」からECSで起動したインスタンスを1つ選択して、パブリックIPアドレスを確認します。
SSHでアクセスします。
$ ssh -i ~/.ssh/MyKeyPair.pem ec2-user@18.208.224.98
[ec2-user@ip-172-31-29-65 ~]$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ce7d4889d153 XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/sample-react-ecs-app "nginx -g 'daemon of…" 6 minutes ago Up 6 minutes 0.0.0.0:32768->80/tcp ecs-sample-react-ecs-app-task-1-sample-react-ecs-app-fec3f4b4e9bfce947d00
91909553a102 amazon/amazon-ecs-agent:latest "/agent" 7 minutes ago Up 7 minutes ecs-agent
[ec2-user@ip-172-31-29-65 ~]$ exit
以下の2つのDockerコンテナが起動しています。
- amazon-ecs-agent: ECSエージェント(AWSのECSの機能を使うためのクライアントのプロセス)
- sample-react-ecs-app: 今回作成したDockerアプリケーション(32768ポートで公開されている)
公開されているポートでブラウザにアクセスしてみます。
正しく表示されました。
ここでDockerコンテナの公開ポートがECSによって自動的に決定されていることに注意してください。これは「動的ポートマッピング(dynamic host port mapping)」によるものです。
動的ポートマッピングが有効になっている場合、Dockerコンテナのホスト側のポートは「32768–61000」の範囲で設定されます。詳しくは公式ドキュメントを参照してください。
ALBによるロードバランシングの設定
ALB(Application Load Balancer)を使用することで、動的ポートマッピングされ、インスタンス内のDockerコンテナにロードバランスすることができます。
「Load Balancers」を選択し、「Create Load Balancer」をクリックします。
「Application Load Balancer」の「Create」をクリックします。
以下を設定し、「Next: Configure Security Settings」をクリックします。
- Name: sample-react-ecs-app-alb
- Scheme: internet-facing
インスタンスを配置したVPCとサブネットを選択し、「Next: Configure Security Settings」をクリックします。
今回はテストなのでセキュリティ設定はせずに「Next: Configure Security Groups」をクリックします。
今回のテスト用のセキュリティグループを選択し、「Next: Configure Routing」をクリックします。
以下を設定し、「Next: Register Targets」をクリックします。
- Target group -> Name: sample-react-ecs-app-target-1
- Target group -> Target type: Instance
- Health checks -> Path: 「/index.html」
後でECSサービスを使ってインスタンスを登録するので、ここではインスタンスを選択せずに「Next: Review」をクリックします。
「Create」をクリックします。
「Close」をクリックして完了です。
ESCサービスの作成
ここまではECS上のDockerコンテナを起動するためにタスクを手動で実行してきましたが、サービスを使うことでそれを自動化できます。
対象のクラスタで「Services」タブを選択し、「Create」をクリックします。
以下を設定し、「Next step」をクリックします。
- Launch type: EC2
- Task Definition: sample-react-ecs-app-task
- Service name: sample-react-ecs-app-service
- Number of tasks: 2
- Placement Template: AZ Balanced Spread
以下を設定し、「Next step」をクリックします。
- Load balancer type: Application Load Balancer
- Load balancer name: sample-react-ecs-app-alb
- Target group name: sample-react-es-app-target-1
以下を設定し、「Next step」をクリックします。
- Service Auto Scaling: Configure Service Auto Scaling to adjust your service’s desired count
- Minimum number of tasks: 2
- Desired number of tasks: 2 (コンテナ2つにしてみます)
- Maximum number of tasks: 4
- Automatic task scaling policies -> Policy name: sample-react-ecs-scaling-policy
「Create Service」をクリックします。
サービスが作成されました。「View Service」をクリックします。
タスクが2つ実行されています。
「Events」タブを選択すると自動で実行されたイベントが確認できます。ALBのターゲットに自動的にインスタンスが登録さていることが確認できます。
アプリケーションの稼働確認
最後にALB経由でDockerコンテナのアプリケーションの稼働を確認してみましょう。
「Load Balancers」から、今回作成したALB(sample-react-ecs-app-alb)を選択し、DNS名をコピーします。
ブラウザにDNS名を入力すると、Reactアプリケーションの画面が表示されました。
これでAWS上で稼働したReactのDockerアプリケーションをALBを使って公開できることが確認できました。
最後に
いかがでしたか?これでECRとECSを使って、AWS上でDockerのイメージ管理やコンテナ運用ができるようになりましたね。Dockerアプリケーションをクラウド上でどんどん運用していきましょう。それでは。
環境
- NodeJS: v11.0.0
- create-react-app: 2.1.1
- Docker: 18.06.1-ce, build e68fc7a
- AWS CLI: aws-cli/1.16.40 Python/3.7.0 Darwin/18.2.0 botocore/1.12.30

