Docker Meetup Tokyo #2 LT「Docker meets AWS OpsWorks」の続き #dockerjp
ども、大瀧です。
昨日行われたDocker Meetup Tokyo #2でLTしてきました。が、5分の持ち時間に全く収まらなかったので、ブログで補足させてください!
Dockerコンテナをデプロイするツールが欲しいというモチベーションから、AWSの提供するデプロイサービスがいくつかあること、OpsWorksがよさそうと思っていたらドンピシャなブログ記事があった!...と話したところでタイムアップになり、肝心のデモと所感が話せなかったんです。LT力不足を痛感。
OpsWorksと組み合わせてできること
dockerコマンドの代わりにOpsWorksを使うメリットは、以下だと思っています。
- Web画面のクリック操作で一発デプロイ!!
- ロードバランサなどと元々連携できるので、有り物で一気に本番レベルの環境に!!
Web画面のクリック操作で一発デプロイ!!
OpsWorksは、AWS Management Consoleの画面上で様々な操作ができます。今回のDockerの構成であれば、Dockerを実行するインスタンスの作成、Dockerのインストール、Dockerイメージの取得、Dockerコンテナの実行が2クリックで実行できます!
インスタンスの作成
起動とセットアップ
ロードバランサなどと元々連携できるので、有り物で一気に本番レベルの環境に!!
OpsWorksはAWSのサービスの1つということで、AWSの各サービスと連動する仕掛けが最初から用意されています。なので、それに乗れれば特別な設定無しで"ロードバランサに登録する"といった本番レベルのデプロイが手軽に実装できます。OpsWorksではあらかじめELBを設定しておくと、インスタンス作成後に自動で登録してくれたりします!
元ネタのブログ記事の構成で動くかを検証し、手順をまとめてみました。
1. Ubuntu 12.04 AMIの準備
ベースイメージは、ブログの通りUbuntu 12.04のEC2インスタンスを用意し、以下のコマンド(DockerをサポートするカーネルのインストールとDockerのaptリポジトリの追加)を実行してからAMIを作成し、用意しました。
$ sudo apt-get update $ sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring $ sudo reboot
$ sudo su # echo deb https://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list # apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 # apt-get update # exit $ exit
2. OpsWorksスタックの作成
続いて、OpsWorksを構成していきます。AWS Management ConsoleでOpsWorksの画面を表示し、[Add Your First Stack]で新規スタックを作成します。
スタック名は任意のものでOK(今回はDockerTest)、リージョンはAMIを作成したところ(今回はOregon)を選択、カスタムAMI、EBS Backed、用意したSSHキーをそれぞれ選択します。そして、画面下の[Advanded >>]で詳細設定を開きます。
ボタンのあったところの表示が[Configuration Management]に切り替わるので、[Use custom Chef cookbooks]を[Yes]に変更、[Repositry URL]は、元のブログ記事で紹介されている、以下のサンプルリポジトリを指定します。
そして、[Custom JSON]には以下を入力します。Dockerイメージ名はDocker Indexで公開されている好きなものに差し替えてください。
{ "my_apps": { "app1": "<DOKER_IMAGE_NAME1>" }, "my_nginx": "<DOKER_IMAGE_NAME2>" }
最後の[Use OpsWorks security groups]は、OpsWorksが用意しているセキュリティグループの使用有無を選択します。あらかじめ別のセキュリティグループがあり、SSHなどを0.0.0.0/0でオープンしたくない場合にはNOにしましょう。
最後に[Add Stack]をクリックし、スタックが作成されます。
3. レイヤーの作成
続いて、OpsWorksインスタンスをグループでまとめる、レイヤーを[Add a Layer]リンクから作成します。
[Layer Type]を「Custom」に変更し、あとは任意のレイヤー名、短縮名で構いません。セキュリティグループもOpsWorksのグループ、既存のグループのどちらでも構いません。
続いて、[Settings]リンクからレイヤーの設定画面を表示します。
メニューバーから[Recipes]をクリックし、レイヤーの各インスタンスで実行するChefレシピを設定します。[Custom Chef Recipes]の文中にある[edit]リンクをクリックします。
スタック設定時に指定したGitリポジトリにあるChefレシピを、OpsWorksライフサイクルイベントに当てはめて行きます。以下のイベントにレシピを入力し[+]をクリックして決定します。
Setup | my_webapp::setup |
Deploy | my_webapp::pull_images と my_webapp::run_containers |
Undeploy | my_webapp::kill_containers |
一通り入力すると、以下のようになります。[Save]ボタンで保存します。
続いて、あらかじめELBが用意されていればレイヤーに登録しましょう(必須ではないので、飛ばしても構いません)。メニューから[Network]を選択し、[Elastic Load Balancer]でELB(今回はDockerELB)を選択し[Save]で保存します。
これで準備OKです!画面右上の[Instances]をクリックし、インスタンス追加画面に切り替えます。
4. インスタンスの作成とDockerコンテナのデプロイ
[Add an Instance]ボタンでインスタンス作成画面を表示します。
[Size]を好みのインスタンスタイプに設定し、あとはスタックおよびレイヤーの初期設定から引っ張ってくれるので、変更の必要がないか確認しましょう。問題なければ、[Add Instance]でインスタンスが作成されます。
作成したインスタンスの[start]をクリックするとインスタンスの立ち上げ、Dockerのセットアップ、コンテナ作成まで一気に進んで行きます!
あとは、インスタンスのステータスが「online」になるまで数分待ちます。onlineになったら、表示されているPublic IPにUbuntuユーザーでSSH接続し、おもむろにdocker psコマンドを実行してみましょう。
ikkomon:chevalglass ryuta$ ssh ubuntu@54.XXX.XXX.XXX The authenticity of host '54.XXX.XXX.XXX (54.XXX.XXX.XXX)' can't be established. RSA key fingerprint is f2:2d:4b:53:26:a9:de:ed:00:f2:47:9d:23:29:8d:6e. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '54.XXX.XXX.XXX' (RSA) to the list of known hosts. This instance is managed with AWS OpsWorks. ###### OpsWorks Summary ###### Operating System: Ubuntu 12.04.4 LTS OpsWorks Instance: docker1 OpsWorks Instance ID: 73486bbf-dbc2-4f3a-96fc-4ab008777a69 OpsWorks Layers: Docker OpsWorks Stack: DockerTest EC2 Region: us-west-2 EC2 Availability Zone: us-west-2c EC2 Instance ID: i-XXXXXXXX Public IP: 54.XXX.XXX.XXX Private IP: 172.31.12.187 VPC ID: vpc-bcc0bbd4 Subnet ID: subnet-bfc0bbd7 Visit http://aws.amazon.com/opsworks for more information. Last login: Fri Apr 11 03:04:34 2014 from XXX.XXX.XXX.XXX dockerubuntu@docker1:~$ sudo docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e5ea6d3ab5a0 dockerfile/nginx:latest nginx 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp nginx 11789622b9e9 dockerfile/ghost:latest bash /ghost-start 4 minutes ago Up 4 minutes 2368/tcp app1,nginx/app_app1 ubuntu@docker1:~$
コンテナが起動していますね! スタック設定のカスタムJSONでmy_nginxのDockerイメージに80番ポートをListenするものを指定していれば、ELBからHTTP接続が転送されるので、WebブラウザからELBに接続してみます。
nginxのデフォルトページが表示されました!nginxコンテナの構成を工夫すれば、アプリコンテナへのリバースプロキシも組めそうですね。(参考 : Nginx dynamic hostname discovery for Docker)
5. ダミーアプリケーションの作成(オプション)
4.までの作業でDockerコンテナは動作するのですが、その後の運用において以下の問題が残ります。
- コンテナの削除のレシピ(my_webapp::kill_containers)を呼ぶ実装が無い
- 従って、コンテナの削除=インスタンスの削除になっている
そこで、OpsWorksのライフサイクルイベントのDeploy/Undeployを利用してみます。Deploy/Undeployを実行するためには、OpsWorksの"アプリケーション"を登録する必要があるため、今回はダミーアプリケーションで対応します。ダミーアプリケーションはその名前の通り、中身のないアプリケーションです。本来、OpsWorksのアプリケーションはGitリポジトリからgit pullするなどのアプリをデプロイするための設定ですが、今回はDockerコンテナにアプリケーションを組み込む仕組みを特に用意していないためDeploymentを実行できるために空のもので代用します。画面左のメニューから[Apps](画面左上のNavigationをクリックし、[Apps])を選択します。
つづいて、[Add an App]をクリックし、作成画面を表示します。
作成画面では、任意のアプリケーション名(今回はDummy)を入力、[Add Type]と[Repository Type]を「Other」に変更したら、あとは既定のまま[Add App]をクリックします。
これで、[Undeploy]でコンテナの削除(docker rm)と[Deploy]でコンテナの実行(docker run)が自由に実行できるようになります。画面左のメニュー(もしくは上の[Navigation])から[Deployments]を選択、[Deploy an App]から[Deploy]/[Undeploy]を実行します。 *1
検証が終わったら、インスタンスの[stop]リンクでシャットダウンし[delete]リンクで削除し後片付けしましょう。
まとめ
スライドの"今後の展望"にも書きましたが、今回のサンプルはごくごく簡単な設定をしたものですので作り込む余地はたくさんあります。Docker x OpsWorksのとっかかりとして、本エントリーを参考にしていただけると幸いです。
脚注
- 今回のサンプルのChefレシピは冪等性を考慮していないため、2回連続でDeploy/Undeployを実行するとエラーになります。 ↩