Git のフックを利用したデプロイの方法

Gitクラウド

Git のフックを利用した本番環境適用の仕組みや post-update などのスクリプトの書き方、必要となる SSH 接続の設定方法を説明します。

Git のフックを利用したデプロイの仕組み
Git には フック【hooks】という仕組みがあり、Git に対するアクションをトリガーとしてなんらかのスクリプト処理を行うことができます。
例えばリモートリポジトリ(中央リポジトリ)に修正コードをpushしたタイミングで本番環境にもその修正コードを自動で反映させる(デプロイ)ということもできます。
基本的には、masterブランチへのpushで本番環境へ、developブランチへのpushでステージング環境へデプロイするフックを作成します。
下図はmasterブランチから本番環境へのデプロイを表しています。

フックによるデプロイ

origin masterへのpush)が完了すると、リモートリポジトリのフックスクリプトが動作します()。
フック処理では本番環境に SSH 接続し、本番環境側からorigin masterpullするよう記述します()。
pullが成功すると本番環境のワーキングディレクトリが更新され、本番用のソースコード等がここへ配置されます。
ワーキングディレクトリの一部をドキュメントルートに指定することにより、利用者は最新の環境をブラウザでアクセスできるようになります。


フックスクリプトの書き方
フックのスクリプトは.git/hooks配下にあります。
フックスクリプトには色々な種類があり、Git へのアクションにおける様々なタイミングでスクリプトを走らせることが可能ですが、デプロイに関しては以下のスクリプトを利用するのが良いでしょう。

post-receive
push処理が終了した後で1回呼び出されます。
引数はありませんが、pushされた参照のリストを標準入力から受け取ることができます。
このスクリプトではpush処理を中断させることはできませんが、クライアント側ではこのスクリプトが終了するまで接続を切断できません。
このスクリプトが出力する標準出力の内容はクライアントに返されます。

post-update
push処理が終了した後で1回呼び出されます。
実際に更新されたすべてのrefの名前を可変数の引数で受け取ります。
このスクリプトではpush処理を中断させることはできませんが、クライアント側ではこのスクリプトが終了するまで接続を切断できません。
このスクリプトが出力する標準出力の内容はクライアントに返されます。

下記は post-update によるフックスクリプトの記述例です。

#!/bin/sh

# 基本的に複数のブランチが同時に更新されることはないため、第一引数をチェックする
if [ $1 = "refs/heads/master" ]; then
	echo "deploy production"
	# GIT_DIR 環境変数が優先されるため、--git-dirでディレクトリを明示指定する
	ssh production "cd /path/to && git --git-dir=.git pull origin master"

elif [ $1 = "refs/heads/develop" ]; then
	echo "deploy staging"
	ssh staging "cd /path/to && git --git-dir=.git pull origin develop"

fi

# リポジトリがHTTP公開の場合に必要(これがないと最新の情報をpullできない)
exec git update-server-info

上記の例では SSH 接続を簡略化するために、.ssh/configファイルを事前に設定しています。

Host production
  Hostname production.myserver.com
  User ec2-user
  IdentityFile /path/to/keys/production.pem

Host staging
  Hostname staging.myserver.com
  User ec2-user
  IdentityFile /path/to/keys/staging.pem


SSHD の設定(Windows Server)
デプロイはリモートリポジトリサーバが修正コードを適用する側のサーバに SSH で接続し、git pullすることで行います。
したがって本番サーバやステージングサーバ側が SSH 接続を受け入れるよう設定する必要があります。
具体的には SSHD(SSH デーモン) を起動し、22 番ポート(変更可能)を開けるという手順になります。
サーバが Linux の場合では SSHD はすでに設定されているかと思いますので、ここでは Windows Server での設定方法について説明したいと思います。

Git for Windows には SSHD も含まれていますのでこれを利用しましょう。
ちなみに Git for Windows は以下の URL からダウンロードできます。

https://gitforwindows.org/

まずは git bash を起動し、SSHD が利用する var フォルダを作成します。

>mkdir /var
>mkdir /var/empty
>mkdir /var/log
>touch /var/log/lastlog # SSH 接続のログファイル

sshd_config ファイルを設定します。
パスワードを聞いてくるとそこでスクリプトがストップしてしまいますので、ここでは公開鍵認証のみ設定します。
LogLevel を DEBUG にしておくことで、エラー発生時の原因究明に役立つログを出力してくれます。

>cd /etc/ssh
>vim sshd_config

・・・
PubkeyAuthentication yes # 公開鍵による認証あり
PasswordAuthentication no # パスワード認証なし
LogLevel DEBUG # デバッグログ
・・・

各種の暗号方式の公開鍵を作成します。

>cd /etc/ssh
>ssh-keygen -t rsa -f ssh_host_rsa_key # RSA方式
>ssh-keygen -t dsa -f ssh_host_dsa_key # DSA方式
>ssh-keygen -t ecdsa -f ssh_host_ecdsa_key # ECDSA方式
>ssh-keygen -t ed25519 -f ssh_host_ed25519_key # EdDSA方式

次に SSH ポートを開放します。
コントロールパネルより、Windows ファイアウォールの「詳細設定」画面を開きます。
(セキュリティが強化された Windows ファイアウォール)

Windowsファイアウォール

受信規則から新しい規則を作成します。

受信規則

ウィザードにしたがってそれぞれ入力していきます。

規則の種類:ポート
プロトコルおよびポート:TCP、特定のローカルポート 22
操作:接続を許可する
プロファイル:ドメイン、プライベート、パブリック
名前:SSH

受信規則ウィザード

受信規則が作成できました。

セキュリティが強化されたWindowsファイアウォール

IP アドレスアクセス制限をかける場合は、作成した規則をダブルクリックし、スコープタブを開きます。
「これらの IP アドレス」を選択し、許容するアドレスを追加します。

IPアクセス制限

SSHD の起動には sshd というユーザが必要です。
セキュリティの観点からデーモンプロセスを root 権限で起動しないための特権分離オプションにより、SSHD は sshd ユーザによって起動されます。
sshd ユーザが存在しない場合は SSHD 起動時に以下のエラーが発生します。

Privilege separation user sshd does not exist

sshd ユーザを追加する手順は以下の通りです。

スタートメニューから「Windows 管理ツール」→「コンピューターの管理」を開き、左メニューの「ローカルユーザーとグループ」→「ユーザー」を選択します。

コンピューターの管理

上部メニューの「操作」から「新しいユーザー」をクリックします。

コンピューターの管理-ユーザーの追加

ユーザー名を sshd としてユーザーを作成します。
パスワードは無期限の方が運用が楽かなと思います。

コンピューターの管理-ユーザーの追加-新しいユーザー

最後に SSHD を起動します。

>/user/bin/sshd.exe

Windows にリブートがかかった場合にも SSHD が起動するようスタートアップに登録しておくと良いでしょう。
スタートアップフォルダは以下になります。

C:/ProgramData/Microsoft/Windows/Start Menu/Programs/Startup


公開鍵の登録
リモートリポジトリサーバ側で SSH キー(公開鍵と秘密鍵)を作成します。
以下は RSA 方式の場合になります。

>ssh-keygen -t rsa -b 4096 -C "johndoe@example.com"

作成された公開鍵を本番サーバ側の SSHD へ登録して完了です。
下記ファイルに id_rsa.pub (RSA方式の場合)の内容を追記します。

Windows Server の場合
C:/Users/{ユーザ名}/.ssh/authorized_keys

Linux の場合
/home/{ユーザ名}/.ssh/authorized_keys

ちなみに、これはリモートリポジトリサーバから本番サーバなどへの SSH 接続の話です(図1の②)。
ややこしい話ですが、Git 環境をクローンするサーバがリモートリポジトリに SSH でアクセスするためには、これとは逆方向の SSH 接続設定が必要ですね(図1の③)。
こちらについては、以下の記事に説明がありますので参照してください。

Git を利用した開発環境の設定



参考: Git を利用した開発環境・テスト環境・本番環境の構成
参考: Git ワークフロー(ブランチモデル)とその手順
参考: Git コンフリクトの解消
参考: git push を Chatwork や Slack へ通知する方法

コメント