SMARTCAMP Engineer Blog

スマートキャンプ株式会社(SMARTCAMP Co., Ltd.)のエンジニアブログです。業務で取り入れた新しい技術や試行錯誤を知見として共有していきます。

Docker ComposeのAmazon ECSデプロイを試してみた

スマートキャンプ、エンジニアの入山です。

2020年7月にDockerとAWSのコラボレーションにより、単一コマンドでDocker ComposeのyamlファイルからAmazon ECS上に各コンテナをデプロイできる機能追加が発表され、非常に注目を集めました!

From Docker Straight to AWS - Docker Blog

AWS and Docker collaborate to simplify the developer experience | Containers

ローカルでDockerを利用して開発を行っている方々は、ほぼ間違いなくDocker Composeを利用してアプリの動作に必要な各コンテナを一括管理しているかと思いますが、このECS Pluginを利用するとAmazon ECSへの各コンテナのデプロイとECSの動作に必要な各AWSリソースを一括して自動構築してくれます。

今回は、そんなDockerのECS PluginがDocker for MacのStable版でリリースされ、実際に試してみたので紹介したいと思います!

DockerのECS Pluginとは

DockerのECS Pluginは、DockerとAWSのコラボレーションにより実現したDockerの拡張機能で、docker-compose.ymlに記述された各コンテナリソースをAmazon ECSのFargate上に直接デプロイすることができる仕組みです。

ローカルで普段実行しているdocker-composeコマンドと同じく、upやdownなどのシンプルな単一コマンドでAWSへのデプロイが自動実行され、ECSの実行に必要な各NW設定や外部公開するためのLBなども一括して作成してくれることが特徴です!

今回は以下のDocker公式ドキュメントを参考に、動作確認を行っていきます。

docs.docker.com

検証環境

今回検証に利用した環境は、以下となります。

7月のリリース当初はDocker for MacのEdge版でしか利用できず、再インストールや既存のイメージが全て消えてしまうなど、リスクも多かったので手を出しにくかったですが、9/15リリースのバージョン2.3.0.5でStable版に統合されたので安心して試すことができます!

事前準備

Amazon ECS用のcontext作成

Dockerコマンドのデプロイ先にAWSを指定するために、専用のContextを作成します。 公式のサンプルに従って、myecscontextという名前でContextのcreateコマンドを実行します。

$ docker context create ecs myecscontext

対話形式で以下内容の入力が求められるので、順番に入力していきます。

  • AWS Profile
    • AWS CLIなどを利用していて既存のProfileが存在する場合は、選択肢から選択が可能
    • 新しくProfileを登録する場合はnew profileを選択し、profile名を入力
  • Region
    • 東京リージョンを指定(ap-northeast-1)
  • Credentials(既存Profileを選択した場合は省略可能)
    • AWS Access Key ID
    • AWS Secret Access Key

Contextの作成が完了したら、作成されたContextの確認を行います。
以下のようにmyecscontextが作成されており、TYPEがecsとなっていれば成功です!

$ docker context ls
NAME            TYPE        DESCRIPTION               ...
default *       moby        Current DOCKER_HOST based configuration 
myecscontext    ecs         ap-northeast-1

ECSアカウント設定変更

DockerのECS Pluginを利用するために、ECSのアカウント設定でサービス名の新しいARN形式のオプトインを有効にする必要があります。有効になっていない場合は、デプロイ時にエラーが発生します。

以下のコマンドでECSの各設定の状況を確認できます。LongArnFormatに関する項目が対象の設定になります。

$ aws ecs list-account-settings --effective-settings
{
    "settings": [
        {
            "name": "containerInstanceLongArnFormat",
            "value": "disabled",
            "principalArn": "arn:aws:iam::123456789012:user/docker-ecs-user"
        },
        {
            "name": "serviceLongArnFormat",
            "value": "disabled",
            "principalArn": "arn:aws:iam::123456789012:root"
        },
        {
            "name": "taskLongArnFormat",
            "value": "disabled",
            "principalArn": "arn:aws:iam::123456789012:user/docker-ecs-user"
        }
    ]
}

LongArnFormatに関する設定を、以下のコマンドを実行して有効化します。

$ aws ecs put-account-setting-default --name containerInstanceLongArnFormat --value enabled
$ aws ecs put-account-setting-default --name serviceLongArnFormat --value enabled
$ aws ecs put-account-setting-default --name taskLongArnFormat --value enabled

こちらの設定については、Edge版で少し内容が異なりますが、以下の記事を参考にさせていただきました!

dev.classmethod.jp

DockerイメージをECRへPush

DockerのECS Pluginを利用してECSへデプロイする場合は、事前にDockerイメージをコンテナレジストリにPushしておく必要があります。今回は同じAWSアカウントのECRをレジストリとして利用します。

Docker公式のリポジトリをcloneし、サンプルアプリケーションのディレクトリに移動します。

$ git clone https://github.com/docker/ecs-plugin.git
$ cd ecs-plugin/example/

今回の要となるdocker-compose.ymlを編集します。

  • imageの部分をECRのリポジトリに変更
image: 012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
  • ECRを利用する場合は、コンテナレジストリの認証が不要のため、以下の部分を削除
x-aws-pull_credentials: <<<your arn for your secret you can get with docker ecs secret list>>>

イメージをPushするため、ECRの認証を行います。

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 012345678901.dkr.ecr.ap-northeast-1.amazonaws.com

Login Succeeded

認証が完了したら、DockerイメージをPushします。

$ docker-compose push
Pushing frontend (012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest)...
The push refers to repository [012345678901.dkr.ecr.ap-northeast-1.amazonaws.com/example]
f180fef4ee81: Layer already exists
2c3fd1bbef62: Layer already exists
4d7eb43f9ca3: Layer already exists
3c3553e7865b: Layer already exists
22ee430ae503: Layer already exists
60faa6c61cf1: Layer already exists
cfd52085ef97: Layer already exists
408e53c5e3b4: Layer already exists
50644c29ef5b: Layer already exists
latest: digest: sha256:0632336b6cd907468e9ea435b5e4039b5cf4450265e62860f62d8d8696fc0109 size: 2201

ECRにイメージがPushされていることを確認します。

$ aws ecr list-images --repository-name example
{
    "imageIds": [
        {
            "imageDigest": "sha256:0632336b6cd907468e9ea435b5e4039b5cf4450265e62860f62d8d8696fc0109",
            "imageTag": "latest"
        }
    ]
}

ここまでで準備は完了です!

ECSへデプロイ

先程作成したECSデプロイ用のContext(myecscontext)を利用するよう、Dockerの設定を変更します。

$ docker context use myecscontext
myecscontext

Contextの変更が完了したら、ローカルでDocker Composeを起動するのと同じようにupコマンドを実行します。これだけで、AWSへのデプロイが始まります!

$ docker compose up
[+] Running 17/17
 ⠿ example                        CREATE_COMPLETE        247.0s
 ⠿ ExampleDefaultNetwork          CREATE_COMPLETE          6.0s
 ⠿ FrontendTaskExecutionRole      CREATE_COMPLETE         22.0s
 ⠿ Cluster                        CREATE_COMPLETE          7.0s
 ⠿ BackendTaskExecutionRole       CREATE_COMPLETE         22.0s
 ⠿ CloudMap                       CREATE_COMPLETE         48.0s
 ⠿ ExampleLoadBalancer            CREATE_COMPLETE        153.0s
 ⠿ FrontendTCP5000TargetGroup     CREATE_COMPLETE          1.0s
 ⠿ LogGroup                       CREATE_COMPLETE          1.0s
 ⠿ ExampleDefaultNetworkIngress   CREATE_COMPLETE          1.0s
 ⠿ FrontendTaskDefinition         CREATE_COMPLETE          3.0s
 ⠿ BackendTaskDefinition          CREATE_COMPLETE          3.0s
 ⠿ BackendServiceDiscoveryEntry   CREATE_COMPLETE          3.0s
 ⠿ FrontendServiceDiscoveryEntry  CREATE_COMPLETE          2.0s
 ⠿ BackendService                 CREATE_COMPLETE         80.0s
 ⠿ FrontendTCP5000Listener        CREATE_COMPLETE          1.0s
 ⠿ FrontendService                CREATE_COMPLETE         82.0s

表示されたリソースのステータスが全てCREATE_COMPLETEとなれば、AWSへのデプロイは完了です!

今回のサンプルアプリケーションでは、ECSのタスクやタスク定義をはじめ、LBやNW関連を含む17リソースが250秒程で自動作成されたようです。

psコマンドを実行すると、各コンテナの稼働状況とLBのエンドポイントが表示されます。

$ docker compose ps
ID                                     NAME                REPLICAS            PORTS
example-BackendService-hfEA5K76syiR    backend             1/1
example-FrontendService-j829cZjBATkR   frontend            1/1                 ExampleLoadBalancer-0123456789012.elb.ap-northeast-1.amazonaws.com:5000->5000/tcp

表示されたLBのエンドポイントにアクセスしてみると、サンプルアプリケーションが動作していることが確認できました!

f:id:mt_iri:20201005231738p:plain

リソースの削除

デプロイしたリソースについては、ローカルのDocker Composeと同じようにdownコマンドを実行するだけで、AWS上の各リソースが一括削除されます。

$ docker compose down

まとめ

今回は、DockerのECS Pluginを利用したAmazon ECSへのデプロイを紹介しました。

以下の記事で紹介したAWS Coplilotなども含め、コンテナアプリの実行環境構築やデプロイが、誰でも簡単に行えるように日々整備されていっており、個人開発アプリの公開や新規プロダクトのプロトタイプ検証など、様々な用途で利用できそうです!

DockerのECS Pluginは、GAに向けて本番アプリケーションの構築を移行できるレベルを目指しているようなので、今後のアップデートが楽しみです。是非皆さんも試してみてください!

tech.smartcamp.co.jp