Amazon EC2 Container Registry(ECR)でECS/Elastic BeanstalkのDockerイメージをホストする(1/12アップデート)

2015.12.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

2016/01/12 Elastic Beanstalkの部分をアップデートしました。

ども、大瀧です。 1週間ほど前に、Dockerレジストリサービス Amazon EC2 Container Registry (以下ECR)がリリースされました。今回は、AWSでDockerを扱う2サービス ECS(EC2 Container Service)とElastic BeanstalkでECRを利用する手順をご紹介します。

とりあえず動かしてみる

ECSのFirst Run画面が更新され、サンプルのECSクラスタに加えてECRリポジトリがサクッと作成できるようになったので試してみます。ECRは現時点ではバージニアリージョンでしか使えないことに注意しましょう。

AWS Management ConsoleからECS管理画面を表示し、バージニア北部リージョンを選択すると、初期画面が表示されます。[Deploy a sample application onto an Amazon ECS Cluster]を選択するとECSクラスタ一式、[Store container images securely with Amazon ECR]を選択するとECRリポジトリが作成されます。今回は両方のチェックをオンにし、[Continue]をクリックします。

ecr01

ウィザードでは、ECRリポジトリの作成画面が先に表示されます。Docker Hubではリポジトリ名がユーザー名/イメージ名という形式でしたが、ECRではユーザー専用のためユーザー名を付ける必要は必ずしもありません。その代わり先に管理画面もしくはAPIからリポジトリを作成しておかないとdocker pushがエラーになるので注意しましょう。PushするDockerイメージがたくさんあるのであればAWS CLIでスクリプト化するのが良さそうですね。

今回はDocker公式のブログエンジンGhostのイメージを試すので、[Repository Name]を「ghost」として[Next step]をクリックします。

ecr02

リポジトリが作成され、そのあとのdocker pushの手順が画面に表示されます。この辺りの操作はDocker HubへのPushと特に変わりません。

ECRへのログイン

ECRの認証はDocker Hubと互換性があり、aws ecr get-loginコマンドでログインコマンドの一式を確認できます。

$ aws ecr get-login --region us-east-1
docker login -u AWS -p <長いパスワード文字列> -e none https://XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com
$

このパスワードには24時間の期限が設定されているので、以下のようにエイリアスを作っておくと、期限が切れたときの再取得が楽にできるでしょう。

$ alias ecrrefresh='aws ecr get-login --region us-east-1 | bash'
$ ecrrefresh
WARNING: login credentials saved in /Users/ryuta/.docker/config.json
Login Succeeded
$

また、認証情報は別のAPIGetAuthorizationTokenで取得することできます。期限のほかクレデンシャルが構造化されて取得できるので、AWS SDKなどを用いるときにはこちらを利用する方が使い勝手が良さそうです。後述のECS AgentもGetAuthorizationTokenを内部で呼んでいるようです。

ECRへのDockerイメージのPush

ローカルに用意したDockerイメージ(事前にdocker pull ghostを実行しました)に、ECRに対応するタグ名を設定してPushします。タグ名はランダムではなく以下の規則があるので、CIツールによる自動化もそこまで難しくはなさそうです。

<アカウントID>.dkr.ecr.<リージョン名>.amazonaws.com/<リポジトリ名>:<タグ名>
$ docker tag -f ghost:latest XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/ghost:latest
$ docker images | grep ghost
ghost                                                latest              d257ec7ecd87        11 days ago         350.7 MB
XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/ghost   latest              d257ec7ecd87        11 days ago         350.7 MB
s
$ docker push XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/ghost:latest
The push refers to a repository [XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/ghost] (len: 1)
  :(中略)
latest: digest: sha256:8adc9901e470e326cefd5236e0e3da0209af314000000c07f9e04c7cfea3bba3 size: 41200
$

ECRにPushできましたっ!AWS Management Consoleは[Next step]でウィザードを進めましょう。

ECSの場合

続いてECS周りの作成画面が表示されます。タスク定義の画面では、[Image]に先ほど作成したECRリポジトリのlatestタグのイメージが自動でセットされます。今回はGhostを実行するイメージなので、Container PortをGhostのデフォルトポート 2368に変更し、[Next step]をクリックします。

ecr04

サービスの設定は従来通りです。ELBの設定を変更し、追加しましょう。

ecr05

必要に応じて、サービス用のIAMロール作成を画面の指示に従って行いましょう。[Next step]をクリックします。

ecr06

クラスタの設定も従来通りです。任意のインスタンスタイプ、キーペアを設定しましょう。

ecr07

インスタンスに設定するIAMロールは注意が必要です。ECRからのDockerイメージのPullはインスタンスで実行するECSエージェントがECRのAPIをコールして行うため、IAMロールにECRに関する権限を与える必要があります。マネージドポリシーのAmazonEC2ContainerServiceforEC2Roleが既に対応しているので、これをIAMポリシーに紐付けて使うのがオススメです。

ecr08

ecr09

[Review & launch] - [Launch Instance & Run Service]で作成が開始します。しばらく様子を見ましょう。

手元で試したときにはサービスの作成でエラーになったため、ECSのサービス管理画面から再度サービスを作成しました。ちょっとした不具合なので、しばらくしたら修正されるでしょう。

ecr10

というわけでECSクラスタおよびサービスが作成され、ECRのDockerイメージがECSで実行されました!念のためELBのホスト名にアクセスしてみると、Ghostの初期画面が表示されます。

ecr11

Elastic Beanstalkの場合

2016/01/12 ECR on Elastic Beanstalkがサポートされました。
2015/12/28時点では動きませんでした。理由は後述します。

Elastic Beanstalkでは、Multi-container DockerDockerという2つのソリューションスタックでDockerがサポートされます。Multi-container Dockerは内部でECSが動くため、ECRとの連携もECSエージェントが上手くやってくれそうです。ECRのGhostイメージを利用するMulti-container Docker向けのDockerrun.aws.jsonファイルを作成しました。

Dockerrun.aws.json

{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "ghost",
      "image": "XXXXXXXXXXXX.dkr.ecr.us-east-1.amazonaws.com/ghost:latest",
      "essential": true,
      "memory": 128,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 2368
        }
      ]
    }
  ]
}

以下のeb createのメッセージにありますが、EBのインスタンスからECS/ECRにアクセスするためにaws-elasticbeanstalk-ec2-roleロールに権限を付与しておきましょう。先ほどのマネージドポリシーAmazonEC2ContainerServiceforEC2Roleが楽です。

では、EBCLIでEnvironmentを作ってみます。

$ eb init
(中略 ECRを利用するためにus-east-1リージョンを選びましょう) 
$ eb create
WARNING: The Multi-container Docker platform requires additional ECS permissions. Add the permissions to the aws-elasticbeanstalk-ec2-role or use your own instance profile by typing "-ip {profile-name}".
For more information see: https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_ecstutorial.html#create_deploy_docker_ecstutorial_role
Enter Environment Name
(default is ECRTest-dev):
Enter DNS CNAME prefix
(default is ECRTest-dev):
  :
(中略)
  : 
ERROR: Encountered error starting new ECS task: {
    "failures": [
        {
            "reason": "ATTRIBUTE",
            "arn": "arn:aws:ecs:us-east-1:XXXXXXXXXXXX:container-instance/639c43f8-9ffb-4656-93a3-01c272285485"
        }
    ],
    "tasks": []
}
(Ctrl + Cでコマンド終了)
$

ちょっと情報少なめのエラーになりました。これは、ECRに対応するECS Agentのバージョンは1.7以上という要件によるもので、現在利用できるMulti-container Dockerソリューションスタックの最新版(v2.0.4)で実行されるECSエージェントのバージョンが1.6と不足しているためです。ソリューションスタックの説明からはECSエージェントのバージョンはわからないので、コンテナインスタンスを立ててaws ecs describe-container-instancesで確認するのが確実です。

ECS Optimised Amazon Linux最新版

$ aws ecs describe-container-instances \
  --container-instances XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX \
  --region us-east-1
(中略)
            "attributes": [
                (中略)
                {
                    "name": "com.amazonaws.ecs.capability.ecr-auth"
                }
            ],
            "versionInfo": {
                "agentVersion": "1.7.0",
                "agentHash": "191dbd5",
                "dockerVersion": "DockerVersion: 1.7.1"
            }
        }
    ]
}
$

EB Multi-container Docker v2.0.4

$ aws ecs describe-container-instances \
  --container-instances XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX \
  --cluster awseb-ECRTest-dev-XXXXXXXXXX \
  --region us-east-1
(中略)
            "attributes": [
                (中略)
                {
                    "name": "com.amazonaws.ecs.capability.logging-driver.syslog"
                }
            ],
            "versionInfo": {
                "agentVersion": "1.6.0",
                "agentHash": "34235e3",
                "dockerVersion": "DockerVersion: 1.7.1"
            }
        }
    ]
}

ソリューションスタックが更新され、ECSエージェントのバージョンが上がれば、ECRが使えるようになると思います。しばし待ちましょう。

まとめ

ECRをECSとElastic Beanstalkで使う手順をご紹介しました。Beanstalkの方は正常稼働を確認したわけではないので、サポート後に問題が無いかどうか、後追いで確認しますね。