ECS CLIというECS専用のCLIツールが先日、発表されました(AWS CLIのECS対応という話ではなく、ElasticBeanstalk用のebコマンドがあるようなイメージと似ていると思います)
このツールの最大の利点としてはDockerComposeで作成したdocker-compose.yml
がECSでも使えるよ!という所だと思います。
自分はDockerComposeを使った事がなかったので、初めにDockerComposeの公式チュートリアルをローカルで試しつつ、その後、ECS-CLIを使ってローカルで作成したものをAWSのECSにデプロイしてみたのでメモ。
結論
- ECS-CLIを使う事をで簡単にDockerComposeで作った環境をAWSにデプロイできる
- コマンドはdocker-composeに似ているので覚えやすい
- ECS-CLIでbuildディレクティブは現在使えないので、利用するイメージは予めビルドしておくこと
- ECS-CLIがGoで書かれており、バイナリなのでインストールが楽
- ECSでt2.microなど少ないスペックで実施する場合、複数コンテナ起動時にメモリ不足で起動できない場合があるので、その場合、mem_limitディレクティブなどで調整が必要
- EC2を意識しないコンテナサービスが出て欲しい。。。。
参考
- Using the Amazon ECS Command Line Interface
- aws/amazon-ecs-cli
- ecs-cli チュートリアル
- ECS CLIでAmazon ECSを操作してみた #reinvent
環境
- MacOSX(10.10.5)
- Docker 1.8.2
- Docker Compose 1.4.0
- ECS CLI v0.1.0
ローカル環境(Mac)でDocker Composeを試す
下記に沿ってやります。
dockerやdocker composeをローカルマシンにインストールしていない場合、説明に従ってインストールしてください。
instalation and set-up
# version確認
$docker-compose --version
docker-compose version: 1.4.0
$mkdir composetest
$cd composetest
2つのファイルを作成します。Pythonのアプリケーション本体とアプリケーションの依存ライブラリの一覧
from flask import Flask
from redis import Redis
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
redis.incr('hits')
return 'Hello World! I have been seen %s times.' % redis.get('hits')
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
flask
redis
Create a Docker image
Dockerfileを作ります。
FROM python:2.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py
- DockerHubのpythonというイメージの2.7というタグがついたイメージを利用
- app.pyとrequirments.txtをDockerイメージの/codeというパス配下に配置
- ディレクトリを /code に移動
-
pip install -r requirements.txt
コマンドを実行し、依存ライブラリをインストール -
python app.py
というコマンドをコンテナ起動時に実行するように設定
Define services
docker-compose.yml
というファイルを作成し、複数のコンテナの定義及び起動時のオプションを設定します。
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/code
links:
- redis
redis:
image: redis
- webとredisというコンテナを使います
- redisコンテナはDockerHubからredisという名前のイメージを取得して利用します
- webコンテナはカレントディレクトリのDockerfileをビルドし、そのイメージを利用します
- Hostの5000ポートにアクセスした場合、コンテナの5000ポートにforwardするようにします
- カレントディレクトリのファイル群をコンテナの
/code
にマウントします。これによって以降、app.pyを変えた場合にコンテナの再ビルドを行う必要がなくなります - redisというコンテナとリンク接続します。これによってwebコンテナからredisコンテナにアクセスできるようにします。リンク設定をするとwebコンテナからはredisというホスト名でredisコンテナにアクセスできるようになり、接続ができます(/etc/hostsにredisホストの情報を追記している)
Build and run your app with Compose
いよいよdocker-composeを使ってみましょう!
イメージのダウンロードを行ってない場合、初回時に実行されるため、多少時間がかかりますが、ゆっくり待ちましょう!
$docker-compose up
....
redis_1 | 1:M 26 Oct 12:35:07.634 * The server is now ready to accept connections on port 6379
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
これでコンテナが起動していますが、フォワグラウンドで起動し、操作できないのでCtrl+Cで一度停止させます。
次は-d
オプションを利用して、起動し、バックグラウンドでコンテナを起動します。
# webとredisコンテナをバックグラウンドで起動
$docker-compose up -d
# docker-composeによって起動しているコンテナ群を確認
$docker-compose ps
Name Command State Ports
-------------------------------------------------------------------------
composetest_redi /entrypoint.sh Up 6379/tcp
s_1 redis-server
composetest_web_ /bin/sh -c Up 0.0.0.0:5000->50
1 python app.py
無事バックグラウンドで指定した2つのコンテナが起動しているのを確認できました。
起動したwebコンテナのアクセスはboot2dockerを使っていない場合、curl http://localhost:5000/
とすることでできますが、自分の場合、Macでboot2docker(DockerMachine)を使っているのでそのIPを使ってアクセスします。
# docker-machineのIPアドレスを確認
$docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
default * virtualbox Running tcp://192.168.99.100:2376
# アクセス。アクセスごとにカウントが増える
$curl http://192.168.99.100:5000/
Hello World! I have been seen 2 times.%
バックグラウンドで起動したコンテナは以下で停止させます。
$docker-compose stop
Amazon ECS CLI Tutorial
次にECS CLIを使ってみます。まずは先ほど作成したDockerComposeのファイルを使わず、公式でドキュメントのチュートリアルをそのまま実行してできる事を確認します。
以下、公式ドキュメントに沿ってやっています。
Using the Amazon ECS Command Line Interface
Installing the Amazon ECS CLI
MacとLinux用のGoで書かれたバイナリをあるようなのでそれを利用します。
# /usr/local/bin/ecs-cliにバイナリを配置
$sudo curl -o /usr/local/bin/ecs-cli https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-darwin-amd64-latest
# 実行権限を付与
$sudo chmod +x /usr/local/bin/ecs-cli
# 確認
$ecs-cli help
Configuring the Amazon ECS CLI
AWSの認証や利用するリージョン、クラスタ名をCLIに教えてあげる必要があります。
設定した内容は~.ecs/config
として保存されるようです
まず、AWS認証情報ですが以下のいずれかで設定が可能です。
- 環境変数の
AWS_ACCESS_KEY_ID
とAWS_SECRET_ACCESS_KE
を指定 - AWS CLIの
aws configure
コマンドなどによって~/.aws/credentials
が存在し、認証情報が記載さている -
ecs-cli configure
コマンドで指定。 例:ecs-cli configure --region us-west-2 --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY --cluster ecs-cli-demo
自分の場合、既にAWS CLIを利用しており、~.aws/credentials
があったのでリージョンとクラスタ名のみ指定します
# configureコマンドで設定
$ecs-cli configure --region ap-northeast-1 --cluster my-cluster
# 確認
$cat ~/.ecs/config
[ecs]
cluster = my-cluster
aws_profile =
region = ap-northeast-1
aws_access_key_id = xxxxx
aws_secret_access_key = xxxxxx
む、キー情報はこちらにも書かれるんですね。。。
Amazon ECS CLI Tutorial
ではチュートリアルをやってみます。
Step 1: Create your Cluster
AWS上でコンテナを起動させるためのAmazon EC2のクラスタを起動する必要が有ります。(正確にはECS AgentやDockerがインストールされたECS readyなEC2の起動)
上記クラスタを起動するためにecs-cli up
コマンドを利用します。
$ecs-cli up --capability-iam --keypair HogeFugaKey
オプションでVPCやinstance type、解放するポートなど色々設定できますので詳細はhelpオプションで確認ください。
なお、起動したEC2を確認するとAMIはECS用の設定がされたAmazonLinuxのようでした。
Step 2: Create a Compose File
Docker-composeのファイルを作成します。
t2.mirocのEC2なので利用するメモリを各コンテナとも256MBとしています。
wordpress:
image: wordpress
mem_limit: 268435456
ports:
- "80:80"
links:
- mysql
mysql:
image: mysql
mem_limit: 268435456
environment:
MYSQL_ROOT_PASSWORD: password
なお現在、すべてのdocker-composeで指定できるディレクテイブが使えるわけではない点が注意点です。
利用できるのは以下のディレクティブでbuild
ディレクティブが使えないのでimageは必ず一旦DockerHubなどに置く必要がある点が注意点です。
- command
- cpu_shares
- entry point
- environment
- image
- links
- mem_limit (in bytes)
- ports
- volumes
- volumes_from
Step 3: Deploy the Compose File to a Cluster
さあ、 ecs-cli compose up
コマンドを利用して、作成したcomposeファイルのコンテナをクラスタにデプロイしてみます。
デフォルトでカレントディレクトリのdocker-compose.yml
ファイルを探しますが、--file
オプションでファイル名を指定することが可能です。
# composeに記載されたコンテナの起動
$ecs-cli compose --file hello-world.yml up
Step 4: View the Running Containers on a Cluster
psコマンドで起動しているコンテナを確認してみます。
# 起動しているコンテナの確認
$ecs-cli ps
Name State Ports TaskDefinition
d2d44fd7-5d14-4510-92ee-3a385d28ac61/wordpress RUNNING 54.64.183.253:80->80/tcp ecscompose-tmp:4
d2d44fd7-5d14-4510-92ee-3a385d28ac61/mysql RUNNING ecscompose-tmp:4
ブラウザでコンテナのIPアドレス(上記では54.64.183.253)にアクセスするとWordPressの画面が表示されました。
Step 5: Scale the Tasks on a Cluster
スケールさせるぞ!と思ったらメモリを足りず失敗。。。
$ecs-cli compose --file hello-world.yml scale 2
INFO[0000] Couldn't run containers reason=RESOURCE:MEMORY
なのでecs-cli scale
コマンドでクラスタとなっているEC2の数を1つから2に増やします。
$ecs-cli scale --capability-iam --size 2
INFO[0001] Waiting for your cluster resources to be updated
INFO[0001] Cloudformation stack status stackStatus=UPDATE_IN_PROGRESS
なるほど。CloudFormationのupdate stackをしているのか。
完了後、再度やってみます。
# 起動
$ecs-cli compose --file hello-world.yml scale 2
# 確認.コンテナが2つから4つになっている
$ecs-cli ps
同じようにIPアドレスにアクセスするとWordPressの画面が確認できました。
Step 6: Create an ECS Service from a Compose File
今まで実行したコンテナはECSでいうタスクというバッチなどに適した実行だったので、次にserviceというWeb/APIに適したものとして実行します。
# 現在利用しているrun taskを停止
$ecs-cli compose --file hello-world.yml down
# 停止を確認
$ecs-cli ps
# serviceとしてコンテナを起動
$ecs-cli compose --file hello-world.yml service up
# serviceとしての起動を確認
$ecs-cli compose --file hello-world.yml service ps
Step 7: Clean Up
最後に環境を削除します。
先ほど作成したserviceを削除し、クラスタインスタンスを削除します。
# serviceの削除
$ecs-cli compose --file hello-world.yml service rm
# クラスタの削除
$ecs-cli down --force
DockerComposeチュートリアルで試したものを適用してみる
最初の項でローカル環境で試したdocker-composeのファイルをECSに適用してみましょう。ただし、ECS CLIで利用できるcomposeファイルではbuildディレクティブが現在使えないのでローカルでイメージのビルドとDockerhubへのpushを行っておくことが必要な点を注意しておきます。
DockerfileのビルドとDockerHubへのpush
最初に作成したwebコンテナをDockerHubへpushします。
DockerHubへのアカウントがない場合、事前に取得しておいてください。
cd ~/composetest
# Dockerfileのビルド。-tオプションで{username}/compose-testというリポジトリを設定。usernameはDockerHubのユーザー名
$docker build -t toshihirock/compose-test .
# DockerHubへのログイン
$docker login
# DockerHubへイメージのpush
$docker push toshihirock/compose-test
DockerComposeのファイル変更
少し変更します。
- webコンテナのイメージをDockerHubにpushしたものに変更
- フォワードするポートを変更
- メモリを設定(t2.microインスタンスのため)
web:
image: toshihirock/compose-test
ports:
- "80:5000"
mem_limit: 268435456
links:
- redis
redis:
image: redis
mem_limit: 268435456
また、上記設定でも今まで同様にローカル環境でdocker-composeコマンドで起動できる事を確認します。
ECS-CLIによる起動
では、先ほどチュートリアルでやった際と同じ要領でやってみます。
# クラスタの起動
$ecs-cli up --capability-iam --keypair HogeFugaKey
# docker-compose.ymlを利用してserviceの起動
$ecs-cli compose service up
# 確認
$ ecs-cli compose service ps
Name State Ports TaskDefinition
e63f0788-2adb-49cb-a9f8-601758f8890a/redis RUNNING ecscompose-composetest:3
e63f0788-2adb-49cb-a9f8-601758f8890a/web RUNNING 52.68.36.117:80->5000/tcp ecscompose-composetest:3
$curl http://52.68.36.117/
Hello World! I have been seen 2 times.
出来ました!
ローカルで作成した環境を簡単にAWSに移行できるのは良いですね!
掃除
綺麗にします
# serviceの削除
$ecs-cli compose service rm
# クラスタの削除
$ecs-cli down --force
お疲れ様でした!