この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
今回はDocker Machine、Docker Swarm、Docker Composeの3つを使って、Amazon EC2でDockerコンテナをオーケストレーションしてみます!
やってみた
Swarmクラスタを作成する
まずは前回と同様に、Docker MachineでSwarmクラスタを作成します。
なおswarm createではdiscovery-stage.hub.docker.comにリクエストしてクラスタIDを取得しているのですが、タイミングによってはエラーが出る事がありました。現在はベータリリースという扱いなので仕方がないかと思いますが、ちょっと注意が必要です。
$ sudo docker run --rm swarm create
4e8ebb66a08f838fe05a36c20341f044
$ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY --amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-master --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 master
$ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY--amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 node1
$ sudo ./docker-machine create --driver amazonec2 --amazonec2-access-key YOUR_ACCESS_KEY --amazonec2-secret-key YOUR_SECRET_KEY --amazonec2-region ap-northeast-1 --amazonec2-ami ami-a1bf56a1 --amazonec2-vpc-id YOUR_VPC_ID--swarm --swarm-discovery token://4e8ebb66a08f838fe05a36c20341f044 node2
作成されたSwarmクラスタはこんな感じ。EC2インスタンスが3台追加されているはずです。
$ sudo ./docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM
master amazonec2 Running tcp://54.178.132.195:2376 master (master)
node1 amazonec2 Running tcp://54.92.24.244:2376 master
node2 * amazonec2 Running tcp://54.178.180.56:2376 master
Docker Composeをインストールする
Docker Composeはバイナリをダウンロードしてくるだけです。
$ curl -L https://github.com/docker/compose/releases/download/1.1.0/docker-compose-`uname -s`-`uname -m` > docker-compose
$ sudo mv ./docker-compose /usr/local/bin
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose 1.1.0
オーケストレーションするDockerコンテナイメージを作成する
今回はWebサーバとMemcachedサーバを構築し、Memcachedにカウンター値を格納して、Webサーバにアクセスするたびにカウントアップする、という仕組みを作ります。このためWebアプリケーションを搭載したWebサーバ用のDockerイメージを作成します。
compose/web/scriptsというディレクトリを作り、その中にWebアプリケーションとなるRubyスクリプトを作成します。
$ mkdir ~/compose/web/scripts
$ vi ~/compose/web/scripts/app.rb
スクリプトの内容はこんな感じ。SinatraでWebサーバとして動作し、DalliによってMemcachedを操作します。Memcachedサーバは固定値を使っています(後述にて説明します)
require 'sinatra'
require 'dalli'
set :environment, :production
dc = Dalli::Client.new('54.178.132.195:11211')
value = Array.new
get '/' do
if dc.get("count") == nil then
dc.set("count", 1)
end
value = dc.get("count")
dc.set("count", value + 1)
"count is " + value.to_s
end
Webサーバ用DockerイメージのDockerfileでは、Docker Language Stackのrubyを使い、gemでSinatraとDalliを追加し、上述のrubyスクリプトを組み込んで起動しています。またSinatraのデフォルトポートである4567をEXPOSEしています。
$ vi ~/compose/web/Dockerfile
FROM ruby:latest
RUN gem install sinatra
RUN gem install dalli
ADD scripts/app.rb /usr/local/bin/app.rb
CMD ["ruby","/usr/local/bin/app.rb"]
EXPOSE 4567
このDockerfileをbuildし、Docker Hubに登録しておきます。
$ sudo docker build -t smokeymonkey/app .
$ sudo docker login
$ sudo docker push smokeymonkey/app:latest
Docker Composeの定義ファイルを作成する
Docker Domposeはdocker-compose.ymlファイルに定義を記述します。今回はwebコンテナとmemcachedコンテナを定義しており、Webコンテナでは前述で作成したWebサーバ用Dockerイメージを指定しています。
$ cd ~/compose/
$ vi docker-compose.yml
web:
image: smokeymonkey/app:latest
ports:
- 4567
memcached:
image: memcached
ports:
- 11211:11211
environment:
- constraint:node==master
memcachedコンテナはconstraint:node行によって必ずmasterノードで起動するように定義しています。これが上述のRubyスクリプトでMemcachedサーバのIPアドレスを固定値として埋め込んでいた理由です。
また、この仕組みでは11211/tcpとコンテナの4567/tcpポートがバインドされるランダムなホスト側ポートを使いますので、セキュリティグループで許可してください。
コンテナオーケストレーションする
さて本題。まず、Swarmクラスタを操作するために、環境変数を定義します。
$ $(sudo ./docker-machine env --swarm master)
次にComposeを操作するための環境変数の定義です。環境変数DOCKER_CLIENT_TIMEOUTはデフォルトでは60秒なのですが、大きなサイズのコンテナイメージを使う場合すぐにタイムアウトしてしまうので、大きく取っておきます。
$ export DOCKER_CLIENT_TIMEOUT=600
では起動!
$ sudo -E /usr/local/bin/docker-compose up -d
Creating compose_web_1...
Creating compose_memcached_1...
$ sudo -E /usr/local/bin/docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------
compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp
compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp
memcachedコンテナとweb_1コンテナが起動しました。試しにweb_1コンテナにアクセスしてみます。
$ curl 54.92.24.244:49153
count is 1
ちゃんとカウントが取れてますね。
コンテナをスケールアップさせる
それではオーケストレーションのキモ、コンテナをスケールさせてみます。
$ sudo -E /usr/local/bin/docker-compose scale web=5
Creating compose_web_2...
Creating compose_web_3...
Creating compose_web_4...
Creating compose_web_5...
Starting compose_web_2...
Starting compose_web_3...
Starting compose_web_4...
Starting compose_web_5...
一気に4つのコンテナが増えました。確認してみます。
$ sudo -E /usr/local/bin/docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------
compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp
compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp
compose_web_2 ruby /usr/local/bin/app.rb Up 54.178.132.195:49155->4567/tcp
compose_web_3 ruby /usr/local/bin/app.rb Up 54.178.180.56:49154->4567/tcp
compose_web_4 ruby /usr/local/bin/app.rb Up 54.92.24.244:49156->4567/tcp
compose_web_5 ruby /usr/local/bin/app.rb Up 54.92.24.244:49157->4567/tcp
Swarmノードに分散されて、Webコンテナが5つに増えています!
カウンタの動作を確認してみます。
$ curl 54.178.132.195:49155
count is 2
$ curl 54.178.180.56:49154
count is 3
$ curl 54.92.24.244:49156
count is 4
$ curl 54.92.24.244:49157
count is 5
問題なく、どのWebサーバにアクセスしても、カウントがアップされていますね!
コンテナをスケールダウンさせる
スケールダウンもコマンド一発でできます。
$ sudo -E /usr/local/bin/docker-compose scale web=1
Stopping compose_web_5...
Stopping compose_web_4...
Stopping compose_web_3...
Stopping compose_web_2...
Removing compose_web_5...
Removing compose_web_4...
Removing compose_web_3...
Removing compose_web_2...
$ sudo -E /usr/local/bin/docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------------------
compose_memcached_1 memcached Up 54.178.132.195:11211->11211/tcp
compose_web_1 ruby /usr/local/bin/app.rb Up 54.92.24.244:49153->4567/tcp
簡単!
さいごに
まだまだベータリリースなので少々動作に気になる点はありますが(特にAPIサーバ側)、かなり楽に展開できました。こうなると今後のECSの展開が気になるところですねー。正式リリースが楽しみです。