強欲で謙虚なツボツボ

趣味の読書の書の方

備忘録(ECR + ECS で複数コンテナ)

各自のPCではdocker-composeを使ってAPI用のコンテナとフロント用のコンテナを作成して開発しているものを、AWS ECSとECRでデプロイする。

AWS上ではdocker-composeが使われるわけではなく、それぞれのコンテナを別々にdockerコマンドで起動しているような感じになる。
なので、コンテナの数だけECRでリポジトリ・ECSでタスクとサービスを設定する必要がある。
docker-compose.ymlで記述しているような環境変数やポートの設定はECR・ECSの設定としてコンソール上で入力していく。

 

 

参考

これらを見ながら作業をしました。

Dockerに慣れてきた人がECSで複数コンテナのデプロイをしてみる - Qiita

Dockerコンテナで作ったアプリをECS+RDSでデプロイする - Qiita

 

手順

Dockerはイメージがあって、それを元にコンテナを作成して、そのコンテナを起動する。
そして、イメージはECR・コンテナの作成と起動はECSで設定するので、ECRでリポジトリを作成してからECSでタスク定義とサービスの設定をする。

 

ECR

Create repository

ECRでDockerイメージを管理するリポジトリを作成する。

API用とフロント用で二つのDockerfileを元としたDockerイメージのために二つのリポジトリを作成する。

  • Visibility setttings:Private
  • Repository name:任意(プロジェクト名-コンテナ名とかが無難)
  • Tag immutability:Disabled
  • KMS encryption: Disabled

Createで作成完了。

 

Push

作成したリポジトリを見るとView push commandsとあるので、それに倣えばいい。
AWS CLIをインストールしておく必要がある。

aws ecr get-login-password --region {リージョン} | docker login --username AWS --password-stdin {AWSアカウントID}.dkr.ecr.{リージョン}/amazonaws.com
# AWS CLIのデフォルトプロファイル以外を使用する場合はプロファイルを指定する
# aws ecr get-login-password --region {リージョン} --pofile {プロファイル名} | docker login --username AWS --password-stdin {AWSアカウントID}.dkr.ecr.{リージョン}/amazonaws.com docker build -t {リポジトリ名} . # Dockerfileがルートディレクトリにない場合はパスを指定する
# dokcer build -t {リポジトリ名} -f {Dockerfileのパス} . dokcer tag {リポジトリ名}:latest {AWSアカウントID}.dkr.ecr.{リージョン}.amazonaws.com/{リポジトリ名}:latest docker push {AWSアカウントID}.dkr.ecr.{リージョン}.amazonaws.com/{リポジトリ名}:latest

 

ECS

クラスター作成→タスク定義→サービス設定

クラスターはdockerインストール済のEC2インスタンスだと思うと楽。
今回は、一つのクラスター内にAPI用のサービスとフロント用のサービスを作成する。

タスクはどのECRリポジトリのイメージを使用してコンテナを作成するかとか環境変数を設定したりする。

サービスはクラスター内でどのタスクを動かすかを決めるようなもの。docker-compose.ymlのservicesだと思うと楽かもしれない。(厳密には全然違うかもしれないけど)
frontendとbackendの二つのサービスになることが多いと思う。

Create Cluster

Step 1: Select cluster template

AWS Fargateでいい場合はNetworking onlyを選択。
Fargateは軽いEC2とでも思えばいい。
EC2みたいにssh接続はできないので異常時に中で確認したりはできない。あと、dockerコンテナのポートをホストで別のポートに結びつけることもできない。(8080:3000みたいな)
開発環境であればFargate、本番環境であればEC2でいいと思う。

Step 2: Configure cluster
  • Cluster name:任意
  • Create VPC:チェック
  • Tags:無記入
  • CloudWatch Container Insights:チェック

Createで作成完了。

Create new Task Definition

API用とフロント用で二つ作成する。
Step2のTask definition nameとTask execution role、Add containerの入力内容以外は同じ。

Step 1: Select launch type compatibility

たぶんクラスターと同じやつを選べばいい。
FARGATEを選択。

Step 2: Configure task and container definitions
  • Task definition name:任意
  • Requires compatibilities:FARGATE(Step 1で選んだやつ)
  • Task role:未選択(IAMロールが必要なら設定)
  • Network mode:awsvpc
  • Operating system family:Linux
  • Task execution role:なければ作成(2回目以降ならば初回で作ったものを選択)
  • Task memory (GB):0.5GB
  • Task CPU (vCPU):0.25 vCPU
  • Add Container:ボタンを押すとコンテナに関する入力欄が表示される
    Container name:任意
    Image:ECRのURIをコピー
    Port mappings:コンテナがListenするポート
    Environment variables:環境変数を設定(docker-compose.ymlのenvironmentやenv_fileの内容)
    その他の項目はそのままにした。
  • Service integration:未チェック
  • Proxy configuration:未チェック
  • Log router integration:未チェック
  • Volumes:未設定
  • Tags:無記入

Createで作成完了。

Create Service

API用とフロント用で二つ作成する。
Step1のTask DefinitionでAPI用・フロント用それぞれ対応するタスクを設定。
Step2のSecurity groupはAPI用とフロント用で分けるため別々の設定。

Step 1: Configure service
  • Launch type:FARGATE(クラスターと同じ)
  • Operating system family:Linux
  • Task Definistion:作ったタスクを選択
  • Platform version:LATEST
  • Cluster:作ったクラスタ
  • Service name:任意
  • Service type:REPLICA
  • Number of tasks:1
  • Minimum healty percent:100
  • Maximum percent:200
  • Deployment circuit breaker:Disabled
  • Deployment type:Rolling update
  • Enable ECS managed tags:チェック
  • Propagate tags from:Do not propagate
Step 2: Configure network
  • Cluster VPCクラスター作成時に自動作成されたVPCを選択
  • Subnets:クラスター作成時に自動生成されたサブネットを全て選択
  • Security groups:そのまま(新規作成)
  • Auto-assign public IP:ENABLED(あとで変更できないので注意)
  • Load balancer type:None(本番環境であればApplication Load Balancerを選択した方がいい)
  • Service discovery (optional):API用のみチェック
Service discovery (API用のみ)

各自のPCでdocker-composeを使用するときは、コンテナ内から別コンテナへアクセスのにコンテナ名を使用(http://api:8080みたいに)すればできる。
サービスディスカバリーはそのような設定をすることができ、Namespace nameにlocal・Service discovery nameにapiと設定すれば、local.api:portでフロント用コンテナ内からAPI用コンテナにアクセスできる。

  • Enable service discovery integration:チェック
  • Namespace:create new private namespace
  • Namespace name:任意
  • Configure service discovery service:Create new service discovery service
  • Service discovery name:任意
  • Enable ECS task health propagation:チェック
  • DNS record type:A
  • TTL:10
Step 3: Set Auto Scaling (optional)

本番であればちゃんと設定したほうがいいと思う。

  • Service Auto Scaling:Do not adjust th service's desired count
Step 4: Review

Step 1~3でしてきた設定を確認。

Create Serviceで作成完了。

クラスターでServicesがACITIVE・TasksがRUNNINGになっていることを確認できたらデプロイ完了。

 

Security Groups

これまでの過程でセキュリティグループが自動作成されているが、デフォルトではポートが80番しか空いていないので、コンテナがListenしているポートを開放する。
また、データーベースでRDSを使用する場合はAPI用のコンテナからのアクセスを許可する必要がある。

 

備考

今回作成したECS・ECRをgithubのプッシュを検知して自動デプロイさせる場合は、こちらを参照。(CodeBuild→CodePipeline)

taopo.hatenablog.com

taopo.hatenablog.com