新年明けましておめでとうございます、永井です。
本年も「カルテットコミュニケーションズ技術ブログ」共々頑張っていきたいと思いますので、宜しくお願い致します。
はじめに
カルテット社内におけるデプロイツールのデファクトスタンダードは、Capistranoです。
機能的には特に不満はないのですが、たまに手の込んだことをやろうとすると途端に躓いてしまった経験が何度かあり、出来ればアプリケーションで利用しているプログラミング言語で良いツールがないかなと思っていました。
そこで今回はDeployerを試してみました。
今回のゴール
- シンプルなPHPのプロジェクト(Silexベース)をDeployerでデプロイする
- CircleCIを利用して、 特定ブランチが更新された時に自動的にデプロイする
Deployerについて
DeployerはPHP製のとてもシンプルなデプロイツールです。
公式サイトを見る限り、
- ロールバック対応
- 並列処理対応
- 独自の処理を拡張可能
などなど、デプロイツールに求められるような機能は一通り揃っているように思えます。
デプロイする為のSilexプロジェクトを作成
今回はSilexのプロジェクトをデプロイしてみたいと思います。
deployer-sample
というプロジェクトを作成します。
$ composer create-project fabpot/silex-skeleton deployer-sample "~2.0"
ディレクトリ構成はこんな感じです。
$ tree -L 1
.
├── LICENSE
├── README.rst
├── bin
├── composer.json
├── composer.lock
├── config
├── deploy.php
├── phpunit.xml.dist
├── src
├── templates
├── tests
├── var
├── vendor
└── web
インストール
公式サイトにはいくつかインストール方法が紹介されていますが、今回は直接pharファイルをダウンロードする方法でいきます。
プロジェクト内の bin
ディレクトリへインストールします。
# path/to/deployer-sample
$ curl -LO https://deployer.org/deployer.phar
$ mv deployer.phar ./bin/dep
$ chmod +x ./bin/dep
設定ファイルの生成
コマンドで自動生成出来ます。
今回はSilexプロジェクトなので、Common
を選択。
コマンド実行したディレクトリに生成されるので、任意の場所に移動しています。
デプロイ用のファイルはプロジェクト内に置くべきかどうかは、ケースバイケースだと思いますが、今回は後々楽をする為にプロジェクト配下の config
ディレクトリ以下に配置します。
# path/to/deployer-sample
$ ./bin/dep init
Please select your project type (defaults to common):
[0] Common
[1] Laravel
[2] Symfony
[3] Yii
[4] Zend Framework
[5] CakePHP
[6] CodeIgniter
[7] Drupal
> 0
Successfully created: /path/to/deployer-sample/deploy.php
$ mv deploy.php ./config/
設定ファイルの設定
見たら分かる感じですね。
主な修正点は
- 各種パス及びホスト名
- PHP-FPMを使っていないので削除
writable_mode
デフォルトではacl
というのが指定されておりsudo
必須の為、今回はシンプルにchmod
を設定
といったところです。
# config/deploy.php
// Configuration
-set('repository', 'git@domain.com:username/repository.git');
+set('repository', 'git@github.com:example/deployer-sample.git');
set('shared_files', []);
-set('shared_dirs', []);
-set('writable_dirs', []);
+set('shared_dirs', ['var/logs']);
+set('writable_dirs', ['var/cache']);
+set('writable_mode', 'chmod');
// Servers
-server('production', 'domain.com')
- ->user('username')
+server('production', 'example.com')
+ ->user('user')
->identityFile()
- ->set('deploy_path', '/var/www/domain.com');
+ ->set('deploy_path', '/var/www/example.com');
// Tasks
-desc('Restart PHP-FPM service');
-task('php-fpm:restart', function () {
- // The user must have rights for restart service
- // /etc/sudoers: username ALL=NOPASSWD:/bin/systemctl restart php-fpm.service
- run('sudo systemctl restart php-fpm.service');
-});
-after('deploy:symlink', 'php-fpm:restart');
-
desc('Deploy your project');
task('deploy', [
'deploy:prepare',
...
ローカルからの実行
ローカルから実行してみます。
前提条件
- 公開鍵方式でデプロイ先サーバへSSH接続が出来る
- 秘密鍵はデフォルトの
~/.ssh/id_rsa
を利用する
# path/to/deployer-sample
$ ./bin/dep -f=./config/deploy.php deploy production
デプロイ先はこんな感じになりました。
$ tree -a -L 2
.
├── .dep
│ └── releases
├── current -> /path/to/deployer-sample/releases/1
├── releases
│ └── 1
└── shared
│ └── var
少し変わっているのは、.dep/releases
というファイルでしょうか。
中身は以下のように、リリースバージョン番号とタイムスタンプの一覧が保存されています。
20161206130959,1
20161206135544,2
CircleCIから自動的にデプロイ出来るようにする
SSHの秘密鍵を設定
Project Setting
> SSH Permissions
にてSSHの秘密鍵をセットします。
今回はホスト名をセットせずに登録しました。
デプロイ先のサーバにも公開鍵をセットします。
circle.ymlを用意
master
ブランチが更新されたらデプロイをするように設定しました。
# path/to/deployer-sample/circle.yml
machine:
timezone: Asia/Tokyo
php:
version: 5.6.22
dependencies:
pre:
- echo 'date.timezone = "Asia/Tokyo"' > /opt/circleci/php/$(phpenv global)/etc/conf.d/date_timezone.ini
deployment:
production:
branch: master
commands:
- |
curl -LO https://deployer.org/deployer.phar
mv deployer.phar /home/ubuntu/bin/dep
chmod +x /home/ubuntu/bin/dep
- dep -f=./config/deploy.php deploy production
deploy.phpの修正
このままだと、デプロイ時にデプロイ先サーバとの接続に失敗してしまいます。
これは、CircleCIのSSH Permissions
でセットした秘密鍵が~/.ssh/id_[HASH]
のようなファイルで保存され~/.ssh/config
にて以下のように解決していることが原因です。
Host !github.com *
IdentitiesOnly no
IdentityFile /home/ubuntu/.ssh/id_[HASH]
Deployerのデフォルトで利用されているSSHクライアントは、秘密鍵のパスがデフォルトで ~/.ssh/id_rsa
にセットされるようになっているため、うまく認証ができません。
いくつか回避方法はありますが、今回はPHPのSSHクライアントではなく、サーバにインストールされているSSHクライアントを利用するようにDeployerの設定を変更して対応しました。
# path/to/deployer-sample
set('writable_dirs', ['var/cache']);
set('writable_mode', 'chmod');
+set('ssh_type', 'native');
これで、自動でデプロイされるようになります!
(実はここが一番ハマりました)
おわりに
PHP製アプリケーションにPHP製デプロイツールを利用することで、学習コストや環境構築コストなど低く抑えることが出来るというのは、ひとつのメリットだと思います。
Capistranoと比較して飛び抜けて優れている点があるかといわれると特にないかもしれませんが、シンプルで拡張しやすく作られており、個人的にはとても好印象でした。