ようへいの日々精進XP

よかろうもん

ecs-cli チュートリアル(2)~ ECR のコンテナイメージを利用する ~

ども、かっぱです。

tl;dr

以前から気になっていた ecs-cli から ECR のコンテナイメージをどうやって使うのか。実際にやってみたら難しくなかったけど念のためにメモっておきます。


memo

試した環境

  • 構築した環境

f:id:inokara:20160227160757p:plain

  • ecs-cli を叩く環境
i$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.2 LTS"

$ ecs-cli --version
ecs-cli version 0.2.1 (e7b6965)

教材

github.com

拙作の pm25.test.inokara.com で提供されている JSON データを S3 から取得してクライアントに返すだけの API サーバーっぽいの。

ECR にコンテナイメージを push するまで

#
# docker-compose build でコンテナイメージをビルドする
#
$ docker-compose build

#
# aws cli で ECR にログインする為のパスワードを取得
#
$ aws --region us-east-1 ecr get-login

#
# docker login でログイン
#
$ docker login -u AWS -p xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e none https://xxxxxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com

#
# aws cli でリポジトリを作成
#
$ aws --region us-east-1 ecr create-repository --repository-name oreno-pm25-api

#
# ビルドしたイメージにタグを付与
#
$ docker tag orenopm25api_web_1 xxxxxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-pm25-api

#
# タグを付与したイメージを ECR に push
#
$ docker push xxxxxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-pm25-api

以上。

docker-compose.yml

ECS 用に docker-compose.yml を作成する。

redis:
  image: redis
  cpu_shares: 100
  mem_limit: 67108864
  ports:
    - "6379"

web:
  image: xxxxxxxxxxxxxxxxxxxxxxx.dkr.ecr.us-east-1.amazonaws.com/oreno-pm25-api
  cpu_shares: 100
  mem_limit: 268435456
  volumes:
    - /tmp/nginx/:/var/log/nginx
  ports:
    - "80:80"
    - "4567:4567"
  links:
    - redis
  environment:
    - REDIS_HOST=redis

redis コンテナは Docker オフィシャルの Redis イメージを利用する。web コンテナは先ほど ECR に push したイメージを利用する。この YAML ファイルを ecs.yml という名前で保存しておく。(ファイル名は任意で OK 牧場)

ecs-cliクラスタ作成、ECS インスタンスの起動

#
# クラスタの初期設定
#
$ ecs-cli configure --region ap-northeast-1 --cluster oreno-pm25-api

#
# 実行すると以下のようなファイルが生成される
#
$ cat ~/.ecs/config
[ecs]
cluster = oreno-pm25-api
aws_profile =
region = ap-northeast-1
aws_access_key_id =
aws_secret_access_key =

#
# ECS インスタンスの起動
#
$ ecs-cli up --keypair xxxxxxxxxxxxxxxxxxx \
  --capability-iam \
  --size 1 \
  --vpc vpc-xxxxxxxx \
  --instance-type t2.micro \
  --subnets subnet-xxxxxxxx,subnet-zzzzzzzz \
  --azs ap-northeast-1a,ap-northeast-1c

(以下のように出力される)

INFO[0000] Created cluster                               cluster=oreno-pm25-api
INFO[0001] Waiting for your cluster resources to be created
INFO[0002] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0062] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0122] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0183] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0243] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS
INFO[0304] Cloudformation stack status                   stackStatus=CREATE_IN_PROGRESS

ecs-cli compose up

準備は整ったのでコンテナを起動する。

$ ecs-cli compose -f ecs.yml up

(以下のように出力される)

ERRO[0000] Error describing task definition              error=ClientException: Unable to describe task definition.
        status code: 400, request id: 6c010388-dd17-11e5-bb49-531dd1d03f3f taskDefinitionName=ecscompose-oreno-pm25-api
INFO[0000] Using ECS task definition                     TaskDefinition=ecscompose-oreno-pm25-api:1
INFO[0000] Starting container...                         container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/redis
INFO[0000] Starting container...                         container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/web
INFO[0000] Describe ECS container status                 container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/redis desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-oreno-pm25-api:1
INFO[0000] Describe ECS container status                 container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/web desiredStatus=RUNNING lastStatus=PENDING taskDefinition=ecscompose-oreno-pm25-api:1
snip...
INFO[0097] Started container...                          container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/redis desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-oreno-pm25-api:1
INFO[0097] Started container...                          container=xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/web desiredStatus=RUNNING lastStatus=RUNNING taskDefinition=ecscompose-oreno-pm25-api:1

それぞれのコンテナが起動したようだ。

ecs-cli compose ps

コンテナの状態を確認してみる。

$ ecs-cli compose -f ecs.yml ps
Name                                        State    Ports                                                 TaskDefinition
xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/redis  RUNNING  xx.xxx.x.xxx:32768->6379/tcp                          ecscompose-oreno-pm25-api:1
xxxxxxxx-0a0a-4871-a644-zzzzzzzzzz/web    RUNNING  xx.xxx.x.xxx:4567->4567/tcp, xx.xxx.x.xxx:80->80/tcp  ecscompose-oreno-pm25-api:1

おけ。どうやらコンテナは正常に起動している。

アプリケーションの確認

デプロイ済みのなんちゃってアプリケーションの動作確認。

$ curl -s 'xx.xxx.x.xxx/json?date=20160224&station_code=40202010' | jq .
{
  "time_series": {
    "24": 3,
    "23": 3,
    "22": 1,
    "21": 7,
    "20": 9,
    "19": 15,
    "18": 13,
    "17": 17,
    "08": 13,
    "07": 21,
    "06": 20,
    "05": 18,
    "04": 15,
    "03": 17,
    "02": 21,
    "01": 20,
    "09": 11,
    "10": 14,
    "11": 17,
    "12": 21,
    "13": 24,
    "14": 23,
    "15": 22,
    "16": 19
  },
  "check_date": "20160224",
  "check_station_code": "40202010",
  "check_station": "国設大牟田"
}

一応、それっぽい JSON のレスポンスが得られた。

後片付け

$ ecs-cli down --force
INFO[0001] Waiting for your cluster resources to be deleted
INFO[0001] Cloudformation stack status                   stackStatus=DELETE_IN_PROGRESS
INFO[0062] Cloudformation stack status                   stackStatus=DELETE_IN_PROGRESS
INFO[0122] Deleted cluster                               cluster=oreno-pm25-api

ecs-cli down --force で一発。


以上

ecs-cli から ECR が使えたのはなんでだろう

ECS インスタンスの起動時に --capability-iam を付与することで以下の IAM ポリシーがコンテナインスタンスに付与されている為に利用できるのかしら。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecs:CreateCluster",
        "ecs:DeregisterContainerInstance",
        "ecs:DiscoverPollEndpoint",
        "ecs:Poll",
        "ecs:RegisterContainerInstance",
        "ecs:StartTelemetrySession",
        "ecs:Submit*",
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:GetDownloadUrlForLayer",
        "ecr:BatchGetImage"
      ],
      "Resource": "*"
    }
  ]
}

なるほど。

ちなみに、上記のポリシーは Managed Policy の AmazonEC2ContainerServiceforEC2Role で適用される。

思ったより簡単だったけど...

  • ECR は東京リージョンにいつくるだんろう...
  • pm25.test.inokara.com をちゃんと作り直したい