Gitlab Community Editionで自動デプロイさせてみる


自分がサボってる間に後輩がバイト先で便利なslackbotを作ってくれた。行動力羨ましい
変更のたびにsshしてpullするのはめんどくさいので自動でデプロイするようにしてみた。前例マシマシなので個人の記録として。ちなみにwebサーバーはnginx+php-fpmです。

デプロイキーを登録する

これまでデプロイの意味すら知らなかったのでまずこれから。Gitlabでは読み込み専用の暗号化鍵を設定できるらしい。設定>リポジトリ>Deploy Keysの項目を開くと設定するメニューがでる。

  • タイトル : サーバーのお名前とか
  • key : ssh-keygenで作った公開鍵

を入力してAdd keyをクリックすれば登録は完了。あとはサーバーのアカウント側で.shh/configを書けばssh経由でのclone/pullができるようになる。[Write access allowed]チェックを抜いたので上にも書いたとおりこのディレクトリからpushはできない。

デプロイするスクリプトを書く

ちょろっとググった結果phpで書くのが良さそうなのでphpで書いた。
やりたいことは

  • 今動いているslackbotのコンテナを止める
  • masterをpullする
  • dockerイメージをbuildする
  • buildしたイメージでコンテナを起動する

できたのがこれ

deploy.php
<?php

set_include_path(get_include_path() . PATH_SEPARATOR . 'phpseclib');
include('phpseclib/Net/SSH2.php');

$secret_key = "SECRETKEY"; //申し訳程度のセキュリティ要素
$LOG_FILE = dirname(__FILE__).'/hook.log'; //ログファイルの設定

//GETで渡されるKEYが上述のものと合わなかったら不正なアクセスとして記録
if ( !isset($_GET['key']) || !($_GET['key']==$secret_key) ) {
    file_put_contents($LOG_FILE, date("[Y-m-d H:i:s]")." invalid access: ".$_SERVER['REMOTE_ADDR']."\n", FILE_APPEND|LOCK_EX);
    exit;
}

file_put_contents($LOG_FILE, date("[Y-m-d H:i:s]")." ".$_SERVER['REMOTE_ADDR']." git issue recieved.\n", FILE_APPEND|LOCK_EX);


$ssh = new Net_SSH2('slackbot_server.local');
if (!$ssh->login('username', 'password')) {
        exit('ログイン失敗');
}
#docker stop
echo $ssh->exec('docker stop $(docker ps | grep slackbot | cut -c 1-12)');
echo $ssh->exec('cd /opt/slackbot&&git pull');
echo $ssh->exec('docker build /opt/slackbot -t slackbot');
echo $ssh->exec('docker run --rm -d slackbot:latest');

deploy.phpと、参照しているライブラリphpseclibをwebサーバーが公開しているディレクトリに置く。

webhookを登録する

Gitlabリポジトリのページを開き 設定>リポジトリ>インテグレーション からWebhookの設定ができる。今回はローテクにGETで認証キーを渡して認証しているのでurlにhttp://{deploy.phpのアドレス}?key=SECRETKEYと打つだけ。1つ下にある[Secret Token]の項目は使わない。更に下にはいつwebhookを叩くかの[Trigger]の項目があるので必要なものにチェックを入れる。今回はmasterにpushされたときだけでいいので[Push events]にチェックを入れ対象のブランチ名をmasterとした。最後に[Add webhook]をクリックすれば登録完了、先程の[Add webhook]の下に登録したwebhookが現れる。念の為[test]を押してテストすることもできる。

できたもの

pushすると以下のような流れで自動的に更新が反映される。
[Dev] --push--> [Gitlab] --webhook--> [webサーバー] --php/ssh--> [slackbotのサーバー]
slackbotのとこでwebサーバーを立てても良かったけどすでに立ってる他のところがあったので流用したかったからちょっと遠回りな方法にみえる。

引っかかったところ

  1. webhookにローカルのwebサーバーのurlを入力するとエラーがでる

    ローカルに立っていても初期設定だとローカルへのwebhookは許可されていないらしい。管理者エリアから 設定>ネットワーク>Outbound requestsの項目を開くとAllow requests to the local network from hooks and servicesなる項目があるのでこれにチェックを入れ保存するとローカルのwebhookを指定できるようになる。

  2. webhookは正常に動いているのが確認できたのにGitlab上でタイムアウトのエラーが出る

    docker stopしたりするのにGitlabのデフォルトのタイムアウトが10秒になっているのが原因だった。Gitlabが立っているサーバーに入り、/etc/gitlab/gitlab.rbを以下のように編集した。

    /etc/gitlab/gitlab.rb
    (前略)
    #gitlab-rails['webhook_timeout'] = 10
    gitlab-rails['webhook_timeout'] = 200
    (後略)
    

    編集の後sudo gitlab-ctl reconfigureを実行して反映するとしっかり待ってくれるようになる。

参考

GitlabのWebhookを使って簡易デプロイ(Webサーバへ)をしてみた - Qiita
GitLab: ローカルを指した外向きWebhookはデフォルト禁止(10.6以降) - taikii blog
Hooks being called many times (#2229) · Issues · GitLab.org / GitLab Community Edition · GitLab