Posted at
ConoHaDay 8

ConoHa で Docker 自動デプロイしたかったから、webhook サーバーを立てた。

More than 1 year has passed since last update.

この記事は ConoHa Advent Calendar 2016の 8 日目の記事です。

こんにちは、keika299 です。

前年度は Mail API について書いたらネタ被りさせてしまいました。ごめんなさい。

でも今年も他の方の事とかあんまり考えてないんで、また被ったら来年も謝る方向でいきます:no_mouth:

さて、今日のテーマはこちら。


ConoHa で Docker コンテナを自動デプロイする

一昨年くらいから流行ってますからね。コンテナ。

で、作ってる Web アプリケーションをコンテナ化したところまではいいんですが、

デプロイどうやってやろうかと。

これまでは、rsync 使って、CI からサーバーに放り込んでたんですが、

なんかこう、githubにコードをプッシュするだけでシューって上手いことなって

かっこいい感じでデプロイされるようにしたいなって。思ったんですよね。


実際にサービスをどのようにつなげるか考える


最初の計画

つまり、こんな感じ。

github に push したら、Webhook で DockerHub で Build が走り、

完成したら ConoHa の実環境にデプロイ。

デプロイ完了の通知を Slack 経由で受け取る。と。

OK、いい感じじゃん。これで行こうか。

って思ったんですが、問題点がありまして。


どうやって Docker コンテナの更新を実現させる?

この部分。

:whale2: Docker Hub でのコンテナビルドが成功したら、それを検知して ConoHa サーバー上で

更新するプログラムを回さないとならんのですね。

コンテナビルドの完了自体は Docker Hub が完了時に Webhook を飛ばしてくれるので良いとして、

問題は「誰が Webhook を受け取るのか?」と言うことになります。

このあたりは、AWS等ではコンテナビルド完了にフックして自動的にコンテナを更新

(しかも Blue-Green Deployment なので無停止)してくれるサービスがあるので、

そういったサービスを利用されている方には無縁の話かもしませんが。


救いの手が差し伸べられた。

で、AWS Lambda みたいなサービスを使って更新することも考えていたのですが、

そんな時に ConoHa 様からこんなお知らせが。

「512 MB プラン、始めました。:thumbsup:

どうせ Webhook で走らせるものは基本軽い処理なのですから、

月々 630 円でサーバー立てられるなら使わない手はないですよね? ね?

で、結局の所の構成は



こんな感じで、 Webhook 用サーバー(ConoHa 512 MBプラン)を仲介するようにしました。


環境を作るぞよ


ここで話さないこと


GitHub -> Docker Hub の連携

Docker Hub から簡単に連携させられますヨ。


ConoHa サーバーのセットアップについて

SSHとかファイアウォールとかの設定があるけど、ここもパス。

誰かが書いてくれるんじゃぁないかな。(適当)

今回はサービス提供側のサーバーで Docker Composeを使うので、

Docker Engine と Docker Compose のインストールもしといてね。


Docker Compose の使い方

公式みて。

今回の想定構成は


version: '2'
services:
target-service:
image: example/target-repo:latest
links:
- another-service
another-service:
image: example/another-repo:latest


Webhook サーバーを立てる

Webhook に使えるサーバーは探せばゴロゴロ出てきそうだが、

個人的に Go 言語の復習をしたかったので、簡単なのを書いた。

とりあえずソースだけ githubの keika299/crocop に置いときます。

こんな感じの


crocop.yml


version: 1
port: 8080
hooks:
- webhook-name:
handle: /webhook-handle-url-here
script: /script/file/path.sh


設定ファイルを本体と同じ場所に置いといて、./crocop start で走らせると

http://example.com/hook/webhook-handle-url-hereへのアクセスで

/script/file/pathを実行するようにしています。


dockerが置いてあるサーバーの更新を走らせる

スクリプトファイルは更新したいサーバーへsshで接続してそちらのスクリプトを走らせたのち、

slackへwebhookを飛ばせばOKなので


/script/file/path.sh



#!/bin/sh

set -e

ssh -i ~/.ssh/server-ssh-key -p 22 username@servername /docker/update/shell/path

curl -X POST --data-urlencode 'payload={"channel": "#target-channel", "username": "webhookname", "text": "Updated docker container.", "icon_emoji": ":whale2:"}' https://hooks.slack.com/services/example


こんな感じ。

ほんとはsshの所で、リモート先でエラーが出たらきちんと終了させて、とかするべきなんだけど

その辺はご自分で頑張ってって感じで。


dockerが置いてあるサーバー側で更新をかける

先ほどsshで走らせる指定をしたシェルを、dockerがある側のサーバーに実際に作る。

今回はdocker-composeを使っているので、


/docker/update/shell/path



#!/bin/sh

set -e

docker pull example/target-repo:latest

docker-compose -f /path/to/docker-compose.yml down --remove-orphans
docker-compose -f /path/to/docker-compose.yml up -d


単純にpullしてから強制的に更新かけてる。

手で更新かけるときに打つコマンドをそのまま放り込んだ。


docker hub に webhook を登録

終わりが見えてきた。

最後に、docker hub に行って、webhook を設定する。

ちなみに、githubとかと連携して automated builds にしておかないと

webhook は設定できない。注意 :grimacing:



webhook の URL は最初の方で設定した

http://example.com/hook/webhook-handle-url-here

を指定する。


完成!

あとは github にプッシュしたら、思い描いていた感じでちゃんとビルド -> 通知までやってくれる。


+αのネタとして

とりあえず今回は Docker の自動デプロイがしたかっただけだったのだけど、

蓋を開けて見たら webhook サーバーを自前で持つ結果となった。

最近のwebサービスはhttpで色々やり取りできるから、

好きなようにwebhookを走らせられるのは結構便利な気がする。

(slackもpayloadいじると設定変えられるので、このwebhookサーバーを仲介するとintegration枠1つだけでたくさんのサービスの通知をやり取りできる。とか。やっていいのか知らんけど。)

512 MBプランで十分だし、IoTとかで需要も伸びそうだし、

みんなで ConoHa の 512 MBプランを契約してwebhookサーバー作って、

ちょっとずつ、このは様に 搾取されて 貢献 :moneybag: できればいいんじゃないかな。


長くてごめんね。歳をとると話が長くなるそうです。

去年はAPIネタ、今年は新しくリリースされた 512 MBプランの使い方の一つについてのネタで書かせてもらいました。

気が早いですが、来年のアドベントカレンダーではどんな新サービスについて書けるかなーって、

とっても楽しみですね。