CLOVER🍀

That was when it all began.

Amazon ECS CLIを使って、ローカルでタスクを実行する

これは、なにをしたくて書いたもの?

Amazon ECS CLIを使うと、Amazon ECSのタスク定義をローカルで実行できるらしいので、ちょっと試してみようかなと。

Amazon ECS CLI

Amazon ECS CLIは、ローカルからAmazon ECS上でのアプリケーションの構築、リリース、運用ができるとされているツールです。

Amazon ECS コマンドラインインターフェースの使用 - Amazon Elastic Container Service

GitHubリポジトリは、こちら。

GitHub - aws/amazon-ecs-cli: The Amazon ECS CLI enables users to run their applications on ECS/Fargate using the Docker Compose file format, quickly provision resources, push/pull images in ECR, and monitor running applications on ECS/Fargate.

このAmazon ECS CLIを使って、task-definition.jsonまたはdocker-compose.ecs-local.ymlからAmazon ECSタスク定義を実行できる
ようです。

ecs-cli local - Amazon Elastic Container Service

Running Tasks Locally

今回は、こちらを簡単に試してみましょう。

環境

今回の環境は、こちら。

$ docker version
Client: Docker Engine - Community
 Version:           20.10.16
 API version:       1.41
 Go version:        go1.17.10
 Git commit:        aa7e414
 Built:             Thu May 12 09:17:23 2022
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.16
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.17.10
  Git commit:       f756502
  Built:            Thu May 12 09:15:28 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.4
  GitCommit:        212e8b6fa2f44b9c21b2798135fc6fb7c53efc16
 runc:
  Version:          1.1.1
  GitCommit:        v1.1.1-0-g52de29d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

Docker Composeも使うようです。

$ docker compose version
Docker Compose version v2.6.0

もっとも、この実行形態ではAmazon ECS CLIは使えなかったのですが…。後に少し細工をします。

Amazon ECS CLIをインストールする

まずは、Amazon ECS CLIをインストールします。

Amazon ECS CLI をインストールします。 - Amazon Elastic Container Service

Windows、Linux、macOSに対応しているようです。

ダウンロード。

$ sudo curl -Lo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-linux-amd64-latest

実行権限の付与。

$ sudo chmod +x /usr/local/bin/ecs-cli

署名の検証についても書かれていますが、今回はパスしておきます。

タスク定義の用意

Amazon ECS CLIを使ってローカルでタスク定義を実行するには、タスク定義を記述したtask-definition.jsonかDocker Composeの
構成ファイルが必要になるようです。

もっとも、task-definition.jsonを使っても結局Docker Composeの構成ファイルを生成するようなのですが。

とりあえず、タスク定義としてこのようなものを用意。

task-definition.json

{
  "containerDefinitions": [
    {
      "name": "nginx",
      "image": "nginx:1.22.0",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 80,
          "hostPort": 80
        }
      ],
      "links": [
        "mysql"
      ],
      "memory": 256
    },
    {
      "name": "mysql",
      "image": "mysql:8.0.29",
      "environment": [
        {
          "name": "MYSQL_ROOT_PASSWORD",
          "value": "password"
        }
      ]
    }
  ],
  "family": "webdb"
}

nginxとMySQLを含めていますが、特に関連はありません…。

Amazon ECS CLIを使って、ローカルでタスクを実行する

では、Amazon ECS CLIを使って、ローカルでAmazon ECSのタスク定義からコンテナを実行していきたいと思います。

手順的にはecs-cli local createでtask-definition.jsonからdocker-compose.ecs-local.ymlを生成するか、ecs-cli local upで
task-definition.jsonからdocker-compose.ecs-local.ymlを生成しつつ実行する方法があるようです。

とりあえず、ドキュメントとヘルプを見てみましょう。

ecs-cli local createは、Amazon ECSタスク定義からDocker Composeの構成ファイルを作成するコマンドです。

ecs-cli local create - Amazon Elastic Container Service

$ ecs-cli local create --help
NAME:
   ecs-cli local create - Creates a Compose file from an ECS task definition.

USAGE:
   ecs-cli local create [command options] [arguments...]

OPTIONS:
   --task-def-file value, -f value    Specifies the filename value that contains the task definition JSON to convert to a Docker Compose file. If one is not specified, the ECS CLI will look for task-definition.json.
   --task-def-remote value, -t value  Specifies the full Amazon Resource Name (ARN) or family:revision value of the task definition to convert to a Docker Compose file. If you specify a task definition family without a revision, the latest revision is used.
   --output value, -o value           Specifies the local filename value to write the Docker Compose file to. If one is not specified, the default is docker-compose.ecs-local.yml.
   --force                            Overwrite output docker compose file if it exists. Default compose file is docker-compose.ecs-local.yml.
   --use-role                         Uses the task role ARN instead of temporary credentials.

ecs-cli local upは、タスク定義からコンテナをローカルで実行するコマンドです。

ecs-cli local up - Amazon Elastic Container Service

$ ecs-cli local up --help
NAME:
   ecs-cli local up - Runs containers locally from an ECS Task Definition. NOTE: Creates a docker-compose file in current directory and a ecs-local-network if one doesn't exist.

USAGE:
   ecs-cli local up [command options] [arguments...]

OPTIONS:
   --task-def-compose value, -c value  Specifies the filename value that contains the Docker Compose content to run locally.
   --task-def-file value, -f value     Specifies the filename value containing the task definition JSON to convert and run locally.  If one is not specified, the ECS CLI will look for task-definition.json.
   --task-def-remote value, -t value   Specifies the full Amazon Resource Name (ARN) or family:revision value of the task definition to convert and run locally. If you specify a task definition family without a revision, the latest revision is used.
   --output value, -o value            Specifies the local filename value to write the Docker Compose file to. If one is not specified, the default is docker-compose.ecs-local.yml.
   --override value                    Specifies the local Docker Compose override filename value to use.
   --force                             Overwrite output docker compose file if it exists. Default compose file is docker-compose.ecs-local.yml.

まずはecs-cli local createを実行してみます。特にファイル名を指定しない場合は、task-definition.jsonを使うようです。

$ ecs-cli local create
INFO[0000] Reading task definition from /path/to/task-definition.json

INFO[0000] Successfully wrote docker-compose.ecs-local.yml
INFO[0000] Successfully wrote docker-compose.ecs-local.override.yml

そして、Docker Composeの構成ファイルが作成されました。

docker-compose.ecs-local.yml

version: "3.4"
services:
  mysql:
    environment:
      AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: /creds
      ECS_CONTAINER_METADATA_URI: http://169.254.170.2/v3
      MYSQL_ROOT_PASSWORD: password
    image: mysql:8.0.29
    labels:
      ecs-local.task-definition-input.type: local
      ecs-local.task-definition-input.value: /path/to/task-definition.json
    networks:
      ecs-local-network: null
  nginx:
    environment:
      AWS_CONTAINER_CREDENTIALS_RELATIVE_URI: /creds
      ECS_CONTAINER_METADATA_URI: http://169.254.170.2/v3
    image: nginx:1.22.0
    labels:
      ecs-local.task-definition-input.type: local
      ecs-local.task-definition-input.value: /path/to/task-definition.json
    links:
    - mysql
    networks:
      ecs-local-network: null
    ports:
    - target: 80
      published: 80
networks:
  ecs-local-network:
    external: true

docker-compose.ecs-local.override.yml

version: "3.4"
services:
  mysql:
    logging:
      driver: json-file
  nginx:
    logging:
      driver: json-file

Amazon ECS CLIで使えるDocker Composeの構文は、こちらのようです。

Docker Compose ファイル構文の使用 - Amazon Elastic Container Service

続いて、ecs-cli local upしてみます。

$ ecs-cli local up

すると、docker-compose.ecs-local.ymlの上書きを聞かれます。

docker-compose.ecs-local.yml file already exists. Do you want to write over this file? [y/N]

結局のところ、必要なのはタスク定義というよりDocker Composeの構成ファイルなわけですね。

で、進めようとするとdocker-composeがないということでエラーになりました。

FATA[0000] docker-compose up failed to start due to:
exec: "docker-compose": executable file not found in $PATH

あくまでdocker-composeが必要なようです…。

仕方がないので、こんなスクリプトを作成。

/usr/local/bin/docker-compose

#!/bin/bash

docker compose "$@"

実行権限を付与。

$ sudo chmod a+x /usr/local/bin/docker-compose

気を取り直して、実行。

$ ecs-cli local up
INFO[0000] Reading task definition from /path/to/task-definition.json
 
INFO[0000] Successfully wrote docker-compose.ecs-local.yml 
INFO[0000] Successfully wrote docker-compose.ecs-local.override.yml 
INFO[0000] The network ecs-local-network already exists 
INFO[0000] The amazon-ecs-local-container-endpoints container already exists with ID fc9f664c8ea0c9b34f8782b47af7b1d51ff4c88799f54241fa37cdf16027cfea 
INFO[0000] Started container with ID fc9f664c8ea0c9b34f8782b47af7b1d51ff4c88799f54241fa37cdf16027cfea 
FATA[0000] Failed to create a SSM client to decrypt secrets due to 
failed to create a new AWS session due to Set a region using ecs-cli configure command with the --region flag or AWS_REGION environment variable or --profile flag: Set a region using ecs-cli configure command with the --region flag or AWS_REGION environment variable or --profile flag

リージョンの指定が必要みたいですね。

AWS_REGIONを指定して実行。

$ AWS_REGION=ap-northeast-1 ecs-cli local up

今度は、うまくいきました。

$ AWS_REGION=ap-northeast-1 ecs-cli local up
INFO[0000] Reading task definition from /path/to/task-definition.json

docker-compose.ecs-local.yml file already exists. Do you want to write over this file? [y/N]
y
INFO[0001] Successfully wrote docker-compose.ecs-local.yml
INFO[0001] docker-compose.ecs-local.override.yml already exists, skipping write.
INFO[0001] The network ecs-local-network already exists
INFO[0001] The amazon-ecs-local-container-endpoints container already exists with ID fc9f664c8ea0c9b34f8782b47af7b1d51ff4c88799f54241fa37cdf16027cfea
INFO[0001] Started container with ID fc9f664c8ea0c9b34f8782b47af7b1d51ff4c88799f54241fa37cdf16027cfea
INFO[0001] Using docker-compose.ecs-local.yml, docker-compose.ecs-local.override.yml files to start containers
[+] Running 2/2
 â ¿ Container ecs-cli-local-mysql-1  Started                                                                                                                               3.4s
 â ¿ Container ecs-cli-local-nginx-1  Started                                                                                                                               2.1s

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

$ ecs-cli local ps
CONTAINER ID        IMAGE               STATUS              PORTS                               NAMES                    TASKDEFINITION
779cd34ab1e5        nginx:1.22.0        Up 4 minutes        0.0.0.0:80->80/tcp, :::80->80/tcp   /ecs-cli-local-nginx-1   /path/to/task-definition.json
e4bb51990b0a        mysql:8.0.29        Up 4 minutes        :0->3306/tcp, :0->33060/tcp         /ecs-cli-local-mysql-1   /path/to/task-definition.json

nginxについては、ポートマッピングをしていたのでローカルポートでアクセスできます。

$ curl -i localhost
HTTP/1.1 200 OK
Server: nginx/1.22.0
Date: Thu, 02 Jun 2022 16:40:51 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Mon, 23 May 2022 23:59:19 GMT
Connection: keep-alive
ETag: "628c1fd7-267"
Accept-Ranges: bytes

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

ちなみに、docker container psで見るとamazon-ecs-local-container-endpointsというコンテナがあったりします。

$ docker container ps
CONTAINER ID   IMAGE                                         COMMAND                  CREATED             STATUS             PORTS                               NAMES
779cd34ab1e5   nginx:1.22.0                                  "/docker-entrypoint.…"   5 minutes ago       Up 5 minutes       0.0.0.0:80->80/tcp, :::80->80/tcp   ecs-cli-local-nginx-1
e4bb51990b0a   mysql:8.0.29                                  "docker-entrypoint.s…"   5 minutes ago       Up 5 minutes       3306/tcp, 33060/tcp                 ecs-cli-local-mysql-1
fc9f664c8ea0   amazon/amazon-ecs-local-container-endpoints   "/local-container-en…"   About an hour ago   Up About an hour   80/tcp                              amazon-ecs-local-container-endpoints

コンテナを停止する時は、ecs-cli local down。

ecs-cli local down - Amazon Elastic Container Service

$ ecs-cli local down

とりあえずはこんなところでしょうか。

だいぶ限定的ではありますが、タスク定義をローカルで試してみる手段のひとつとして把握していてもよいのかな、と思いました。