始めに
この記事は、Bluemix Users Group
で開催された2018_GWもくもく会の活動ログです。
私は主催者ではありませんが、このグループは非常に活動が活発で、困った時に皆さんが助けてくれる温かいコミュニティと思います。
既にIBM Cloud
を使っている方も、これから使ってみたいという方も、ぜひぜひ、参加してみてください。
https://bmxug.connpass.com/
環境について
ツールチェーンでは、様々なバージョン管理の仕組みが提供されていますが、ソース管理はGitHubを使っている前提とします。
また、この記事でデプロイする対象はLaravel
です。ただ、他の言語やフレームワークでも応用が効くと思います。
↓↓ちなみに、LaravelをIBM Cloudに乗せる方法はこちら↓↓
IBM CloudにLaravelをデプロイする方法
実現したこと
現在、個人の開発でIBM Cloud(ライトアカウント)を使っています。これまでは
- ソースを修正
- GitHubにコミット&Push
- 環境変数(.envファイル)をローカル環境からサーバー用に書き換え
- 手動でIBM Cloudにデプロイ
この流れで開発をしていました。このやり方でも決して開発は出来るのですが、.envを書き換え忘れていらぬ不具合を起こしたりと、あまりスマートな手法ではありませんでした。
という事で、IBM Cloudにはツールチェーン
を使って、GitHubへのPush以降を自動で行えるようにしてみます。
【新しい流れ】
- ソースを修正
- GitHubにコミット&Push
- GItHubの更新をIBM Cloudが検知して、アプリケーションをビルド
- ビルドされたアプリケーションを自動でデプロイ
実際の手順について
ツールチェーンを設定する
Cloud Foundryアプリを開き、画面左側の概要をクリック。画面右下に「継続的デリバリー」があるので、「有効化」をクリック
下記の画面が出るので、「作成」をクリック
今回はGitHubを使うので、デフォルトのGitを削除(キャプチャはIssueを削除しようとしていますが、Gitを削除すれば両方とも消えます)
画面右上のツールの追加より、GitHubを追加。認証が求められるので、GitHubのアカウントを認証。
今回は既存のリポジトリを使うので、リポジトリ―タイプを「既存」に変更し、ソースリポジトリのURLを入力して「統合の作成(または保存)」をクリック
Delivery Pipelineを設定する。
Build Stageの設定
Delivery Pipelineをクリックすると、デフォルトで「Bulid Stage」と、「Deploy Stage」が用意されています。
Build Stageを変更していきましょう。
Build Stageの右上の歯車マークから、「ステージの構成」をすると…
下記の画面が表示されます。まずは、「入力」の設定をしていきいます。
Gitリポジトリで、自分のリポジトリを選択します。ブランチも必要に応じて変更しましょう。
Laravelの環境変数を設定する。
変更したら、ジョブの設定をします。ビルダータイプをシェルスクリプトに変更します。
ちなみに、シンプルの場合はGitリポジトリからクローンをするだけの様です。これをシェルスクリプトに変更する事でクローン後の処理を定義する事が出来ます。
シェルスクリプトの例は下記の通りです。
#!/bin/bash
# your script here
# change .env
# Database
cp ./htdocs/.env.example ./htdocs/.env
# DB_HOSTをローカルサーバから、ClearDBに変更
sed -i -e "s/DB_HOST=127.0.0.1/DB_HOST=cleardb.net/g" ./htdocs/.env
# 以下、チェンジをしていく
Laravel
の環境変数である、.env
をリポジトリにある.env.sample
からコピーしてサーバ環境用に置換する処理です。(これが無いと、後続のComposer updateで失敗します)
↑↑記事訂正↑↑
先日はこの様に書きましたが、実はLaravelは
.envファイルにあるすべての変数は、サーバレベルやシステムレベルで定義されている、外部の環境変数によってオーバーライドすることができます。
でした…詳細はこちら
というわけで、シェルで環境変数を書き換えていくのはあまり良い手段ではないです。セキュリティ上もあまりお勧めではないので、Cloud Foundryの環境変数を定義してしまいましょう。
環境変数はランタイム⇒環境変数⇒ユーザー定義から可能です。
(下記の例としては、APP_DEBUG
をfalse
にしています。同様にDBへの接続情報等も定義してしまいましょう。)
こうすればシェルの中では、
cp ./htdocs/.env.example ./htdocs/.env
をするだけでOKです。それすら面倒な場合は、環境変数でAPP_ENV
をprodutction
等としたうえで、.env.production
をダミーで作っておくと良いと思います。(内容は.env.sample
と同じでOK)
Deploy Stageの設定
Build Stageと同様に「ステージの構成」をクリックすると、デプロイ・スクリプトの構成が出来ます。
私の環境だけかもしませんが、認証のコマンドを入れないと、Deployに失敗します。(自動でやってくれれば良いのに…)
#!/bin/bash
bluemix api https://api.xxx-xxx.bluemix.net
bluemix login -u test@example.com -o testProject -s testSpace -p Password
cf push "${CF_APP}"
# View logs
# cf logs "${CF_APP}" --recent
最後に
上記の設定を行う事で、GitHubの更新後に更新したソースを自動でデプロイする事が出来るようになりました。
ツールチェーンにはこれ以外にも様々な機能があるので、試してみるのも面白いと思います。
番外編
上記の手法に至るまで、様々な試行錯誤がありました。
composer.json
に.envのコピーを組み込み、cloud foundryの環境変数で上書きする、というものでした。
これをしてしまうと、composer.json
がIBM Cloudに依存してしまいローカルで動かなくなってしまうので私は採用しなかったのですが、
非常に参考になるスクリプトでしたので、残しておきます。
"post-update-cmd": [
"echo post-update-cmd",
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\"",
"sed -i -e s/DB_CONNECTION=mysql/DB_CONNECTION=pgsql/g .env",
"sed -i -e s/DB_HOST=127.0.0.1/DB_HOST=`echo $VCAP_SERVICES | jq .elephantsql[0].credentials.uri | awk -F\/ '{print $3}' | awk -F: '{print $2}' | awk -F'@' '{print $2}'`/g .env",
"sed -i -e s/DB_USERNAME=homestead/DB_USERNAME=`echo $VCAP_SERVICES | jq .elephantsql[0].credentials.uri | awk -F\/ '{print $3}' | awk -F: '{print $1}'`/g .env",
"sed -i -e s/DB_DATABASE=homestead/DB_DATABASE=`echo $VCAP_SERVICES | jq .elephantsql[0].credentials.uri | awk -F\/ '{print $4}' | rev | cut -c 2- | rev`/g .env",
"sed -i -e s/DB_PASSWORD=secret/DB_PASSWORD=`echo $VCAP_SERVICES | jq .elephantsql[0].credentials.uri | awk -F\/ '{print $3}' | awk -F: '{print $2}' | awk -F'@' '{print $1}'`/g .env",
"sed -i -e s/DB_PORT=3306/DB_PORT=`echo $VCAP_SERVICES | jq .elephantsql[0].credentials.uri | awk -F\/ '{print $3}' | awk -F: '{print $3}'`/g .env",
"mkdir -p /tmp/app/bootstrap/cache",
"mkdir -p /tmp/app/storage/framework/sessions",
"mkdir -p /tmp/app/storage/framework/views",
"mkdir -p /tmp/app/storage/framework/cache",
"Illuminate\\Foundation\\ComposerScripts::postUpdate",
"php artisan key:generate"
],