【Docker × ECS入門】docker compose upでECSデプロイ


DockerのECS Pluginがリリースされ、Docker for MacのStable版にも対応したみたいなので、試してみました。

公式ドキュメントや解説サイトもありますが、所々つまづいた点もありましたので、
(いつの間にかdocker ecs composeコマンドがdocker composeに統合されてたり...)
ECS初心者の自分用メモとしてまとめてみました。

検証環境

AWS CLIはバージョン2系が必須です。
Docker、AWS CLIともに最新版にアップデートしておくことをおすすめします。

参考リンク:
AWS CLI の設定
macOS での AWS CLI バージョン 2 のインストール、更新、アンインストール

Dockerイメージの準備

今回はDocker公式サンプルを使用します。
まずはローカルでの動作を確認します。
ほぼ公式Docに書いてあるのですが、自分用メモとしてDocker公式サンプルでの手順を解説していきます。

  • Docker公式サンプルをpull
$ git clone https://github.com/docker/ecs-plugin.git
$ cd ecs-plugin/example/
  • exampleという名前でタグを付け、appディレクトリをビルド
$ docker build app -t example
  • タグを指定して、イメージが作成されていることを確認
$ docker images --filter reference=example
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
example             latest              33e46b7030e0        4 minutes ago       52.3MB
  • ローカル動作確認
$ docker run -t -i -p 5000:5000 example
Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

http://0.0.0.0:5000/ にアクセスしてみてください。
redisが起動していないため、
redis.exceptions.ConnectionError
が発生するはずです。
CTRL+C で終了します。

Amazon ECR でのセットアップ

Amazon ECRは、DockerHubみたいなものです。
作成したDockerイメージをECRにpushし、docker-compose使用時にpullします。

※ ECRへプッシュの段階ではdefaultコンテクストを使用します。
(特段使用していなければ、defaultになってるはず)

$ docker context use default
$ docker context ls

IAMユーザー準備

こちらも公式Docに沿ってIAMユーザーを作成します。
手順通り、「Administrator」という名前で作成します。
作成したIAMユーザーでサインインすると、
ナビゲーションバーに「Administrator@ aws_account_id」が表示されます。
ex. Administrator@1234-5678-9012

認証情報は後ほど使用するため、メモしておいてください。
aws_account_id
aws_access_key_id
aws_secret_access_key

コンソールからデフォルトレジストリに対して認証する

筆者の場合は東京リージョン(ap-northeast-1)を使用します。
[aws_account_id]にナビゲーションバーで確認したaws_account_idをハイフンなしで入力。
ex. 1234-5678-9012 => 123456789012

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [aws_account_id].dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

レポジトリを作成

これで Amazon ECR にプッシュするイメージが用意できたので、それを保持するレポジトリを作成します。
example:latest というレポジトリを作成し、先ほど作成したexampleイメージをプッシュします。

  • レポジトリを作成
$ aws ecr create-repository \
        --repository-name example \
        --image-scanning-configuration scanOnPush=true \
        --region ap-northeast-1 
  • リポジトリにプッシュするイメージにタグ付け
$ docker tag example:latest [aws_account_id].dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
  • イメージをプッシュ
$ docker push [aws_account_id].dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
  • 確認
$ aws ecr list-images --repository-name example

docker-compose ローカル動作確認

ECRにプッシュしたイメージをプルして、ローカルで動作確認を行います。
ERCにイメージがプッシュできているか確認しましょう。
Amazon ECR コンソール (https://console.aws.amazon.com/ecr/) を開きます。
exampleリポジトリが作成されているはずです。

URLをコピーします。
docker-compose.ymlのimageに貼り付け、docker-compose up します。
x-aws-pull_credentialsは今回は不要なため、コメントアウトします。

example/docker-compose.yml
version: "3.8"
services:
  frontend:
    build: app
    # x-aws-pull_credentials: <<<your arn for your secret you can get with docker ecs secret list>>>
    image: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
    ports:
      - "5000:5000"
    depends_on:
      - backend
  backend:
    image: redis:alpine
$ docker-compose up

ECRにプッシュしたイメージをプルできるため、ローカルでアプリの動作を確認できます。

redisも動作確認できました。

$ docker-compose down

ECSへデプロイ

AWS Context作成

docker docs(翻訳)通り、myecscontextという名前で作成します。
先ほどIAMで作成した認証情報を使います。
aws_access_key_id
aws_secret_access_key

$ docker context create ecs myecscontext
? Select AWS Profile new profile
? profile name myecscontext
? Region ap-northeast-1
? Enter credentials Yes
? AWS Access Key ID aws_access_key_id
? Enter AWS Secret Access Key aws_secret_access_key
Successfully created ecs context "myecscontext"

contextを確認

$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
myecscontext        ecs                 ap-northeast-1                 

myecscontextを使用

$ docker context use myecscontext

※セットアップでエラーが出る場合

this tool requires the "new ARN resource ID format"

long ARN formatを有効にする必要があるみたいです。
おまじないだと思って実行します。

$ aws ecs put-account-setting-default --name awsvpcTrunking --value enabled
$ aws ecs put-account-setting-default --name containerInsights --value enabled
$ 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

ECSへデプロイ

やっとECSですが、一瞬で終わります。
docker compose upすると自動でリソースを作成し、デプロイしてくれます。

※ハイフン注意
○ docker compose
× docker-compose

$ docker compose up
WARN[0000] services.build: unsupported attribute        
[+] Running 17/17
 ⠿ example                        CREATE_COMPLETE                                                                                                          204.0s
 ⠿ ExampleLoadBalancer            CREATE_COMPLETE                                                                                                          122.0s
 ⠿ FrontendTCP5000TargetGroup     CREATE_COMPLETE                                                                                                            1.0s
 ⠿ CloudMap                       CREATE_COMPLETE                                                                                                           51.0s
 ⠿ FrontendTaskExecutionRole      CREATE_COMPLETE                                                                                                           22.0s
 ⠿ LogGroup                       CREATE_COMPLETE                                                                                                            3.0s
 ⠿ ExampleDefaultNetwork          CREATE_COMPLETE                                                                                                            8.0s
 ⠿ Cluster                        CREATE_COMPLETE                                                                                                            6.0s
 ⠿ BackendTaskExecutionRole       CREATE_COMPLETE                                                                                                           21.0s
 ⠿ ExampleDefaultNetworkIngress   CREATE_COMPLETE                                                                                                            1.0s
 ⠿ FrontendTaskDefinition         CREATE_COMPLETE                                                                                                            3.0s
 ⠿ BackendTaskDefinition          CREATE_COMPLETE                                                                                                            4.0s
 ⠿ FrontendServiceDiscoveryEntry  CREATE_COMPLETE                                                                                                            3.0s
 ⠿ BackendServiceDiscoveryEntry   CREATE_COMPLETE                                                                                                            1.9s
 ⠿ BackendService                 CREATE_COMPLETE                                                                                                           68.0s
 ⠿ FrontendTCP5000Listener        CREATE_COMPLETE                                                                                                            1.0s
 ⠿ FrontendService                CREATE_COMPLETE                                                                                                           68.0s

デプロイしたアプリを確認

起動しているコンテナの状態を確認。

$ docker compose ps
ID                                     NAME                REPLICAS            PORTS
example-BackendService-xSDWkSABSvEt    backend             1/1                 
example-FrontendService-0pIz1giwUZg4   frontend            1/1                 ExampleLoadBalancer-xxxxxxxxxx.elb.ap-northeast-1.amazonaws.com:5000->5000/tcp

frontendのPORTSにアクセスしてみてください。
サンプルアプリがデプロイできているかと思います。
http://ExampleLoadBalancer-xxxxxxxxxx.elb.ap-northeast-1.amazonaws.com:5000/
ロードバランサーのリスナーポートをTCP:5000からTCP:80に変更するとポート指定なしでアクセスできるかと思います。(反映に少し時間がかかります)

デプロイしたリソースの削除

docker compose downすると、自動でリソースを削除してくれます。

$ docker compose down
[+] Running 17/17
 ⠿ example                        DELETE_COMPLETE                                                                                                                515.0s
 ⠿ ExampleLoadBalancer            DELETE_COMPLETE                                                                                                                389.0s
 ⠿ FrontendTCP5000TargetGroup     DELETE_COMPLETE                                                                                                                389.0s
 ⠿ CloudMap                       DELETE_COMPLETE                                                                                                                514.0s
 ⠿ FrontendTaskExecutionRole      DELETE_COMPLETE                                                                                                                393.0s
 ⠿ LogGroup                       DELETE_COMPLETE                                                                                                                471.0s
 ⠿ ExampleDefaultNetwork          DELETE_COMPLETE                                                                                                                467.0s
 ⠿ Cluster                        DELETE_COMPLETE                                                                                                                467.0s
 ⠿ BackendTaskExecutionRole       DELETE_COMPLETE                                                                                                                472.0s
 ⠿ ExampleDefaultNetworkIngress   DELETE_COMPLETE                                                                                                                  3.0s
 ⠿ FrontendTaskDefinition         DELETE_COMPLETE                                                                                                                390.0s
 ⠿ BackendTaskDefinition          DELETE_COMPLETE                                                                                                                467.0s
 ⠿ FrontendServiceDiscoveryEntry  DELETE_COMPLETE                                                                                                                389.0s
 ⠿ BackendServiceDiscoveryEntry   DELETE_COMPLETE                                                                                                                467.0s
 ⠿ BackendService                 DELETE_COMPLETE                                                                                                                464.0s
 ⠿ FrontendTCP5000Listener        DELETE_COMPLETE                                                                                                                388.0s
 ⠿ FrontendService                DELETE_COMPLETE                                                                                                                386.0s

参考文献

Docker公式サンプル
ECS での Docker コンテナーのデプロイ
AWS CLI を使用した Amazon ECR の開始方法
Fargate を使用した Amazon ECS の開始方法
DockerとAWSのコラボによりdocker ecsコマンドが爆誕したので使ってみた
Docker ComposeのAmazon ECSデプロイを試してみた