Docker Meetup Tokyo #2 LT「Docker meets AWS OpsWorks」の続き #dockerjp

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

ども、大瀧です。
昨日行われた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クリックで実行できます!

インスタンスの作成

docker-opsworks01

起動とセットアップ

docker-opsworks02

ロードバランサなどと元々連携できるので、有り物で一気に本番レベルの環境に!!

OpsWorksはAWSのサービスの1つということで、AWSの各サービスと連動する仕掛けが最初から用意されています。なので、それに乗れれば特別な設定無しで"ロードバランサに登録する"といった本番レベルのデプロイが手軽に実装できます。OpsWorksではあらかじめELBを設定しておくと、インスタンス作成後に自動で登録してくれたりします!

docker-opsworks03-1

元ネタのブログ記事の構成で動くかを検証し、手順をまとめてみました。

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]で新規スタックを作成します。

docker-opsworks04

スタック名は任意のものでOK(今回はDockerTest)、リージョンはAMIを作成したところ(今回はOregon)を選択、カスタムAMI、EBS Backed、用意したSSHキーをそれぞれ選択します。そして、画面下の[Advanded >>]で詳細設定を開きます。

docker-opsworks05

ボタンのあったところの表示が[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にしましょう。

docker-opsworks06

最後に[Add Stack]をクリックし、スタックが作成されます。

3. レイヤーの作成

続いて、OpsWorksインスタンスをグループでまとめる、レイヤーを[Add a Layer]リンクから作成します。

docker-opsworks07

[Layer Type]を「Custom」に変更し、あとは任意のレイヤー名、短縮名で構いません。セキュリティグループもOpsWorksのグループ、既存のグループのどちらでも構いません。

docker-opsworks08

続いて、[Settings]リンクからレイヤーの設定画面を表示します。

docker-opsworks09

メニューバーから[Recipes]をクリックし、レイヤーの各インスタンスで実行するChefレシピを設定します。[Custom Chef Recipes]の文中にある[edit]リンクをクリックします。

docker-opsworks10

スタック設定時に指定したGitリポジトリにあるChefレシピを、OpsWorksライフサイクルイベントに当てはめて行きます。以下のイベントにレシピを入力し[+]をクリックして決定します。

Setup my_webapp::setup
Deploy my_webapp::pull_images と my_webapp::run_containers
Undeploy my_webapp::kill_containers

docker-opsworks11

一通り入力すると、以下のようになります。[Save]ボタンで保存します。

docker-opsworks12

続いて、あらかじめELBが用意されていればレイヤーに登録しましょう(必須ではないので、飛ばしても構いません)。メニューから[Network]を選択し、[Elastic Load Balancer]でELB(今回はDockerELB)を選択し[Save]で保存します。

docker-opsworks13

これで準備OKです!画面右上の[Instances]をクリックし、インスタンス追加画面に切り替えます。

docker-opsworks14

4. インスタンスの作成とDockerコンテナのデプロイ

[Add an Instance]ボタンでインスタンス作成画面を表示します。

docker-opsworks15

[Size]を好みのインスタンスタイプに設定し、あとはスタックおよびレイヤーの初期設定から引っ張ってくれるので、変更の必要がないか確認しましょう。問題なければ、[Add Instance]でインスタンスが作成されます。

docker-opsworks16

作成したインスタンスの[start]をクリックするとインスタンスの立ち上げ、Dockerのセットアップ、コンテナ作成まで一気に進んで行きます!

docker-opsworks17

あとは、インスタンスのステータスが「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に接続してみます。

docker-opsworks18

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])を選択します。

docker-opsworks19

つづいて、[Add an App]をクリックし、作成画面を表示します。

docker-opsworks20

作成画面では、任意のアプリケーション名(今回はDummy)を入力、[Add Type]と[Repository Type]を「Other」に変更したら、あとは既定のまま[Add App]をクリックします。

docker-opsworks21

これで、[Undeploy]でコンテナの削除(docker rm)と[Deploy]でコンテナの実行(docker run)が自由に実行できるようになります。画面左のメニュー(もしくは上の[Navigation])から[Deployments]を選択、[Deploy an App]から[Deploy]/[Undeploy]を実行します。 *1

検証が終わったら、インスタンスの[stop]リンクでシャットダウンし[delete]リンクで削除し後片付けしましょう。

まとめ

スライドの"今後の展望"にも書きましたが、今回のサンプルはごくごく簡単な設定をしたものですので作り込む余地はたくさんあります。Docker x OpsWorksのとっかかりとして、本エントリーを参考にしていただけると幸いです。

脚注

  1. 今回のサンプルのChefレシピは冪等性を考慮していないため、2回連続でDeploy/Undeployを実行するとエラーになります。