Docker Contextを使ってECSにデプロイするよ
AWSのFargateを用いた環境でサービスを提供する際、基盤となる環境はTerraformで構築し、Fargate上で動作するコンテナについてはamazon-ecs-cliやecspressoなどのツールを用いてコンテナの展開を行なっていた。
amazon-ecs-cliとecspressoどちらもyaml形式で設定ファイルを記述し、コマンドを実行するだけで設定ファイルに記述した内容通りにサービスの作成やタスクの実行が行われるようになるため非常に便利。素敵なツールをありがとうございます。
しかしながら上記のツールを使わずとも、2020年末ごろからDockerコマンドのみでECSへのコンテナの展開を完結できるようになっていたらしい。パッと見た感じ、Docker ComposeのCompose fileのような形式で記述でき、AWSリソースの設定箇所も x-aws-
プレフィックスで記述されているため分かりやすい。
順序よくやっていく。
ECSコンテキストの作成。
認証情報にはaws-cliで使用していたdefaultのプロファイルを使用する。
$ docker context create ecs my-ecs-context
? Create a Docker context using: An existing AWS profile
? Select AWS Profile default
Successfully created ecs context "my-ecs-context"
現在のコンテキストの切り替え。
先ほど作成したECSコンテキストにを使用する。
$ docker context use my-ecs-context
my-ecs-context
コンテキストの一覧。
コンテキストが切り替えられていることを確認する。
$ docker context ls
default moby Current DOCKER_HOST based configuration unix:///var/run/docker.sock swarm
my-ecs-context * ecs
Dockerの構成ファイルを作成する。
試しに最小限でnginxを用いたwebサーバを立ててみる。
services:
web:
image: nginx:alpine
ports:
- "80:80"
コンテナを起動する。
コマンド実行後はリソースの作成が行われるため、少し時間がかかる。
$ docker compose up
[+] Running 14/14
⠿ learn-docker-context-ecs CreateComplete 205.1s
⠿ LogGroup CreateComplete 2.0s
⠿ WebTCP80TargetGroup CreateComplete 1.0s
⠿ CloudMap CreateComplete 47.0s
⠿ WebTaskExecutionRole CreateComplete 26.0s
⠿ Cluster CreateComplete 6.0s
⠿ DefaultNetwork CreateComplete 6.0s
⠿ DefaultNetworkIngress CreateComplete 1.0s
⠿ Default80Ingress CreateComplete 1.0s
⠿ LoadBalancer CreateComplete 122.0s
⠿ WebTaskDefinition CreateComplete 3.0s
⠿ WebServiceDiscoveryEntry CreateComplete 2.0s
⠿ WebTCP80Listener CreateComplete 3.0s
⠿ WebService CreateComplete 59.0s
ECSのクラスター、サービス、タスクの生成のみを行なってくれるのかと思いきや、ロードバランサまで作られており、ECSサービスと紐づいていた。そして作成されたロードバランサのDNS名にアクセスすると、Nginxの起動時の画面が表示された。
VPCなどの設定に関してはdefaultのものが使用されているようだった。
もはや簡略化されすぎてて逆に意味不明すぎる。
docker compose up
を実行した結果、どのリソースが作成・変更されたのか分からん。
試しにVPCだけ作成して、Docker構成ファイルにVPC ID指定した後に docker compose up
を実行してみた。
x-aws-vpc: "[作成したVPCのID]"
services:
web:
image: nginx:alpine
ports:
- "80:80"
$ docker compose up
VPC [作成したVPCのID] should have at least 2 associated public subnets in different availability zones
異なるアベイラビリティゾーンのpublicなサブネットが2つ必要らしく、コンテナの起動に失敗する。
アベイラビリティゾーンを二つ用意し、それぞれにpublicサブネットを配置して同様に実行してみた。
上手く起動でき、Nginxにアクセスできた。
docker compose up
[+] Running 14/14
⠿ learn-docker-context-ecs CreateComplete 214.1s
⠿ Cluster CreateComplete 6.0s
⠿ DefaultNetwork CreateComplete 6.0s
⠿ WebTCP80TargetGroup CreateComplete 2.0s
⠿ WebTaskExecutionRole CreateComplete 23.0s
⠿ CloudMap CreateComplete 48.0s
⠿ LogGroup CreateComplete 2.0s
⠿ LoadBalancer CreateComplete 123.0s
⠿ DefaultNetworkIngress CreateComplete 1.0s
⠿ Default80Ingress CreateComplete 1.0s
⠿ WebTaskDefinition CreateComplete 3.1s
⠿ WebServiceDiscoveryEntry CreateComplete 2.0s
⠿ WebTCP80Listener CreateComplete 4.0s
⠿ WebService CreateComplete
このときに作成されたリソースを確認していく。
ちなみにインターネットゲートウェイがなかったら起動失敗する。
VPC [作成したVPCのID] has no internet gateway (Service: AmazonElasticLoadBalancing; Status Code: 400; Error Code: InvalidSubnet; Request ID: hogehoge; Proxy: null)
CloudTrailの証跡を見て、作成されたリソースをざっと書く。
docker-compose.yaml にオプションなど書いていないため、基本的に作成されるリソースのオプションはデフォルトになってるはず。
CloudFormation
docker compose up
コマンド実行時に最初に CloudFormation にテンプレートが登録される。
リソースの作成状態などは CloudFormation 上で管理されるようで、ローカルには state ファイルのようなものは作られない。また AWS に作成されるリソースの命名には、 docker compose up
実行時のカレントディレクトリ名が使用されるため、別のプロジェクトで同じフォルダ名を使用していると事故る可能性がある(多分)
ECS
- Cluster
- Fargate
- Service
- 許可されたVPC: 作成したVPC
- 許可されたサブネット: 作成した2つのpublicサブネット
- セキュリティグループ: docker compose up時に作成されるセキュリティグループ
- パブリックIPの自動割り当て: ENABLED
- TaskDefinition
- Fargate
- タスクサイズ
- タスクメモリ(MiB): 512
- タスクCPU(単位): 256
- コンテナの定義
- web
- Web_ResolvConf_InitContainer
- コマンドに謎のコマンドが指定されている
- ["ap-northeast-1.compute.internal","learn-docker-context-ecs.local"]
- コマンドに謎のコマンドが指定されている
- ServiceDiscovery Service
Security group
- Security group rule 1
- Type: HTTP
- Protocol: すべてのプロトコル
- Port: 80
- Source: 0.0.0.0/0
- Security group rule 2
- Type: すべてのトラフィック
- Protocol: すべてのプロトコル
- Port: すべてのポート
- Source: Ingress2自身(自身のネットワーク内での通信を許可してる)
EC2
- LoadBalancer
- Type: application
- Scheme: internet-facing
- IP Type: ipv4
- Availability zone: 作成した2つのpublicサブネット
- Security group: docker compose up時に作成されるセキュリティグループ
- Listener
- TargetGroup
- Target type: IP
- IP address type: IPv4
- Protocol(Port): HTTP(80)
- Protocol version: HTTP1
CloudWatch Logs
- Name: /docker-compose/learn-docekr-context-ecs
IAM Role
- 以下のポリシーを持つロールが作成される
- AmazonEC2ContainerRegistryReadOnly
- AmazonECSTaskExecutionRolePolicy
雑に図に追記したが、イメージとしてはこんな感じ。
// TODO: TerraformでSecurity Group, RDSなど作成してDocker Context ECSを使ってみる