本記事はDocker Advent Calendar 2015の13日目の記事です。
概要
先日の DockerCon Europe 2015において、Docker社は「Container as a Service」という戦略を打ち出しました。詳しくはpublickeyさんの記事を見ていただければと思いますが、ここで紹介されているデモが非常に興味深かったので、再現してみることにしました。
作成するデモの内容
Github > Travis CI > Docker Hub > Tutum のCI/CDパイプラインを作ります。上記記事で紹介されているデモと少し流れが違いますが、やりたいことは同じです。git push
するだけで、テストが実行され、Dockerイメージがビルドされ、最終的にはアプリがデプロイされるという自動化フローを作ります。
Tutumについて
Docker社が今年の10月に買収したコンテナのデプロイサービスです。位置付け的にはKubernetesやMesosなどと同じくコンテナのスケジューリング機能を持つサービスですが、Dockerホストクラスタを直感的なGUIで簡単にクラウド上に用意できることから、より開発者フレンドリーなサービスだと言えると思います。VMから下の管理を全てTutumに任せることができるため、ユーザは開発に集中することができます。まだベータ版であることから、誰でも無料で試すことができます1。
Tutumはそれ自体がクラウドを持っているわけではなく、Tutumを通してAWSやDigital Oceanといったクラウドサービス上にDockerホストクラスタを構築し、そのクラスタ上にコンテナを配置していくという形になります。今回はAWSを利用します。
デモに利用するアプリについて
AngularJSのチュートリアルで使用されているangular-phonecatというアプリを利用することにします。これを自分のGithubリポジトリにforkする形で進めていきます。
事前準備
以下の準備をしておいてください。なお、Macを前提とします。
- Github上でangular-phonecatリポジトリをforkする
- Homebrewをインストールする
- Google Chromeをインストールする
- Docker Toolboxをインストールし、dockerコマンドがたたける状態にする
- AWSアカウントのアクセスキーとシークレットアクセスキーを取得しておく
- TutumがEC2等を操作するため、適切な権限が付与されている必要があります。詳しくは公式ドキュメントを参照してください
nodebrewのインストール
angular-phonecatはnode.jsを使用します。以下の手順でnode.jsが使えるようにしておきます。
$ brew install nodebrew
$ echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile
$ nodebrew install-binary v0.12.9
$ nodebrew use v0.12.9
$ node -v
v0.12.9
$ npm -v
2.14.9
アプリの実行確認
angular-phonecatがどんなアプリなのか、まずは試しておきましょう。forkしたリポジトリをクローンし、アプリを実行してみます。
$ git clone https://github.com/tktk8924/angular-phonecat.git
$ cd angular-phonecat
$ npm install
$ npm start
ブラウザでhttp://localhost:8000/app
にアクセスすると、アプリが表示されます。
今度はテストを実行してみます。このリポジトリにはユニットテストとE2Eテストが用意されています。E2Eテストは実際に稼働しているアプリに対してテストが行われるので、アプリは起動したままにしておいてください。
$ npm test
...
Chrome 47.0.2526 (Mac OS X 10.11.1): Executed 5 of 5 SUCCESS (0.077 secs / 0.073 secs)
Firefox 41.0.0 (Mac OS X 10.11.0): Executed 5 of 5 SUCCESS (0.06 secs / 0.058 secs)
TOTAL: 10 SUCCESS
$ npm run protractor
...
7 tests, 11 assertions, 0 failures
上記のように出力されていればテスト成功です。
Dockerコンテナ化
angular-phonecatは最終的にDockerコンテナとしてTutum上にデプロイされることになりますので、Dockerfileを作成してイメージをビルドできるようにします。
Dockerfileの作成
以下の内容でDockerfileを作成します。
FROM node:0.12
WORKDIR /app
COPY ./ .
RUN npm install
RUN node_modules/.bin/bower --allow-root install
EXPOSE 8000
CMD ["npm", "start"]
Dockerfileはクローンしたリポジトリのルートディレクトリに置いてください。
$ tree angular-phonecat -L 1
angular-phonecat
├── Dockerfile
├── LICENSE
├── README.md
├── app
├── bower.json
├── node_modules
├── package.json
├── scripts
└── test
コンテナの起動テスト
イメージをビルドして、アプリがコンテナで動作することを確認します。Dockerfileがあるディレクトリで以下のコマンドを実行します。
$ docker build -t angular-phonecat .
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
angular-phonecat latest 88fd1db238cb 10 minutes ago 855.8 MB
イメージができたらコンテナを起動してみましょう。以下のコマンドを実行してください。
$ docker run -d -p 8000:8000 --name angular-phonecat angular-phonecat
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
58b967642168 angular-phonecat "npm start" 11 minutes ago Up 10 minutes 0.0.0.0:8000->8000/tcp angular-phonecat
http://{Your Docker Host IP}:8000/app
にアクセスして、アプリが表示されることを確認してください。
GithubとTravis CIの連携
まずはGithubとTravis CIを連携させ、git push
に対して自動でテストが実行されるようにしましょう。
Travis CIにログインし、プロファイルページで該当のリポジトリを有効にします。下記のようになればOKです。
Docker Hub Automated Buildの設定
続いて、Docker Hubに自動ビルド(Automated Build)の設定を行います。Travis CIにてテストが成功したら、さきほど作成したDockerfileを使って自動でイメージがビルドされるようにします。
Docker Hubにログインし、Linked Accounts & ServicesページでGithubとリンクしておきます。途中で聞かれるアクセス権限については、Public and Private(Recommended)の方を選択してください。下記のようになればOKです。
次に、画面右上のCreate > Create Automated Buildをクリックします。するとGithubのリポジトリ一覧が表示されるので、angular-phonecatをクリックします。
ここではShort Descriptionにてきとうな文字列を入れ、Createをクリックします。
これでDocker Hub上にangular-phonecatリポジトリが作成されました。
Build Settingsに移動して、「When active, builds will happen automatically on pushes.」のチェックを外します。Githubへのプッシュではなく、Travis CIをビルド開始のトリガーにするためです。
さらに画面下の方にあるBuild TriggerのところのActivate Triggersをクリックします。するとこのイメージのビルドを開始するためのTrigger URLが表示されます。Travis CIからこのURLにHTTP POSTすることで、イメージのビルドが開始されます。
Github > Travis CI > Docker Hub のフローを自動化する
それでは、git push
によってDockerイメージがビルドされるところまでを自動化しましょう。
angular-phonecatリポジトリにはTravis CIのビルド設定ファイルである.travis.yml
がすでに含まれていますが、これを以下のように変更したいと思います。
language: node_js
node_js:
- 0.12
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm start > /dev/null &
- npm run update-webdriver
- sleep 3
script:
- node_modules/.bin/karma start test/karma.conf.js --no-auto-watch --single-run --reporters=dots --browsers=Firefox
- node_modules/.bin/protractor test/protractor-conf.js --browser=firefox
after_success: .travis/after_success.sh
after_success
はscript
のテストが成功したら実行されるスクリプトです。テストが成功したらDocker Hubでイメージをビルドするようにします。下記のスクリプトファイルを作成してください。Trigger URLはご自分の環境に合わせて修正してください。
#!/bin/bash
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
curl -i -H "Content-Type: application/json" --data '{"source_type": "Branch", "source_name": "master"}' -X POST {Your Trigger URL}
fi
※このままではTrigger URLはGithub上で公開されることになってしまいます。Trigger URLが知られてしまうと誰でもイメージのビルドができてしまうので危険です。Travis CIではこのような秘密にしておきたいデータを暗号化して記述できるようにする機能がありますので、そちらを利用してください。
$TRAVIS_PULL_REQUEST
はTravis CIによって提供される環境変数で、ビルドするコードのリビジョンがプルリクされたものかどうかを判別するために使います。Dockerイメージのビルドはmasterブランチにマージされたコードを使って行いたいのでこのような書き方をしています。
もともとあったscriptsディレクトリは不要なので削除します。また、after_success.sh
に実行権限をつけます。
$ rm -fr scripts
$ chmod +x .travis/after_success.sh
これで準備は完了です。これまでの変更をコミットしてgit push
しましょう。Travis CIでテストが実行され、Docker Hubでイメージがビルドされるはずです。
$ git add .
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: .travis.yml
new file: .travis/after_success.sh
new file: Dockerfile
deleted: scripts/private/README.md
deleted: scripts/private/old/README.md
deleted: scripts/private/old/ScrapeData.js
deleted: scripts/private/old/format-json.sh
deleted: scripts/private/old/goto_step.bat
deleted: scripts/private/old/goto_step.sh
deleted: scripts/private/old/snapshot.sh
deleted: scripts/private/push-to-github.sh
deleted: scripts/private/retag.sh
deleted: scripts/private/test-all.sh
deleted: scripts/private/update-gh-pages.sh
deleted: scripts/update-repo.sh
$ git commit -m "Add Dockerfile and integration with Docker Hub"
$ git push -u origin master
Travis CIのビルド完了画面
Docker HubのBuild Details画面
Tutum利用準備
ようやくTutumを使うところまで来ました。さっそくログインしてみましょう。Docker Hubのアカウントでログインできます。
ログインしたら、まずはTutumをAWSとリンクさせます。画面右上のアカウントをクリックし、Account infoページに移動してください。
次に、Amazon Web ServicesのAdd credentialsボタンをクリックして、アクセスキーとシークレットアクセスキーを入力します。これでAWSとのリンクは完了です。
それでは、Dockerホストクラスタを構築します。TutumではDockerホストをNodeと呼んでいます。Launch new node clusterをクリックしてください。
とりあえずNode cluster nameだけ入力し、Launch node clusterをクリックします。するとNodeが1台EC2上に構築されます。VPCやセキュリティグループなど、必要な設定はTutumが全てやってくれます。
Nodeが構築されました。
アプリのデプロイ
Nodeが構築され、コンテナをデプロイする準備ができました。いよいよangular-phonecatアプリをデプロイします。あんまり面白くありませんが、とりあえずangular-phonecatコンテナを1台デプロイしてみることにします。
Tutumでは同じイメージから起動されたコンテナの集まりをServiceと呼びます。Create serviceをクリックしてください。
まずはイメージを選択します。Public repositories > Search Docker hubと進んで、さきほど作成した自分のangular-phonecatイメージリポジトリ名を入力します。そしてSelectをクリックしてください。
続いてServiceの設定です。一箇所だけ、Portsの設定を修正します。Publishedにチェックを入れて、Node portに80を指定します。これでangular-phonecatコンテナに対してインターネット上からポート80番でアクセス出来るようになります。docker run -p 80:8000
と同じ意味ですね。修正できたらCreate and deployをクリックしてください。
これでコンテナのデプロイが始まります。Docker Hubからイメージをpullし、AWS上のNode内にコンテナが起動します。デプロイが完了するとこんな感じの画面が確認できると思います。
それではangular-phonecatアプリにアクセスしてみましょう。Endpointsタブを開いてください。
するとService endpointsというところにServiceのURLが表示されています。このURL(に/app
を加えて)をブラウザで開いてください。
angular-phonecatアプリが表示されました。これでアプリのデプロイは完了です。
Docker Hub > Tutum Redeployのフローを自動化する
最後に、Docker HubとTutumを連携させます。Docker Hubにてイメージが更新されたら、さきほどデプロイしたコンテナを自動でRedeploy(コンテナを停止し、最新のイメージをpullして新しいコンテナをデプロイする)します。こうすることですぐに変更が反映されるようになります。
さきほどデプロイしたコンテナ(Service)の画面からTriggersタブに移動します。ここでTriggersというものを登録します。TriggersというのはTutumのAPIの一つであり、外部のプログラムからこのAPIにHTTP POSTすることで、ServiceをRedeployさせることができます。Add trigger欄に任意の文字列を入力し、+Addをクリックします。
Triggerが登録されました。このURLをDocker Hub側からPOSTすることで、Serviceの自動Redeployを可能にします。URLはコピーしておいてください。
今度はDocker Hub側にWebhookの設定を追加します。Docker Hub上のangular-phonecatリポジトリページに行き、その中のWebhooksというタブに移動してください。
Add Webhookをクリックし、さきほどコピーしたURLを登録します。
Webhookが登録されました。これでDockerイメージが更新されるたびにコンテナがRedeployされ、変更が自動で反映されるようになります。
お疲れ様でした。これで全ての設定が完了しました。
Git Push!!
アプリに変更を加えてgit push
してみましょう。app/partials/phone-list.html
の6行目に以下のコードを追記してください。検索ボックスの上に見出しをつけます。
<h1>Angular Phonecat</h1>
コミットしてgit push
しましょう。
$ git commit -am "Add heading"
$ git push origin master
ServiceのURLにアクセスしてみましょう。下記のような画面になっていれば成功です。
おわりに
今回はGithub>Travis CI>Docker Hub>TutumというCI/CDパイプラインを作ってみましたが、このパイプラインの組み合わせは色々なパターンがあると思います。特に企業のプロダクションで利用するということであれば、イメージをprivateにしておきたいはずです。実はTutumにはPrivate Registryの機能があって、直接Tutumにイメージをプッシュすることで、イメージをprivateに利用できるようになっています。
本記事ではDockerコンテナベースの自動化フローの構築を目的としていたので、コンテナ1台立ち上げただけのシンプルな構成でしかTutumを使用しませんでした。しかし、Tutumはすでにプロダクションで利用できるだけの非常に多岐に渡る機能を持っていて、今後注目されていくサービスになることは間違いないでしょう。
-
2015年Q3にプロダクションレディーになるということなので今すぐ試しましょう! ↩