2015新卒の@kadoyauです。学部時代はロボットをいじり、院で音の情報処理をC++で書いていましたが、入社後は楽しくちょっと大きな金槌でWeb開発をしています。ヒヤッホォォォウ!PHP7は最高だぜぇぇぇぇ!!(ぐるぐる目)
サンタさんが来るお家をつくろう
クリスマス もとい紅莉栖マスまであと2日になりました。
紅莉栖マスといえばサンタさん。今日は、あなたの会社に2日でサンタさんを呼ぶ方法をお教えしたいと思います。
煙突をビルドする
雇われサンタさんの収入は一定の時間内にデプロイできたプレゼントの価値で決まります。ということは、サンタさんはプレゼントを高速にデプロイするための煙突を有した家を好みそうです。煙突のない家にプレゼントをデプロイするのはめんどくさいですよね。
サンタさんを迎えるために、まず煙突をDokkuをつかってビルドしましょう!
Dokkuって何?
サービスをつくってデプロイするのは、ちょっと気合を入れないとめんどくさいものです。
サービスをつくりたいのに、それに必要なDBや環境の構築もいちいちしなくてはならない。サンタさんはプレゼント(サービス)をデプロイするのをためらうってわけです。
HerokuのようなPaaSが社内で使えると、環境構築はHerokuにまかせて、サンタさんはコードと設定を少し書くだけで気軽にデプロイできて便利です。
Dokkuを使うと、DockerベースのHerokuライクなPaaSを作ることができます。これが煙突です。まずは次の記事などを参考に、1日で煙突をビルドしましょう。
参考:DockerでミニHeroku!「Dokku」をさくらのクラウドで試す - さくらのナレッジ
これでサンタさんを呼ぶ準備は整いました。
プレゼントをデプロイする
翌朝目を覚ますと、サンタさんからの手紙(中身は業務委託を契約するための書類でした)があなたのもとへ届いていました。
「やれやれ、仕方ないな」あなたはそう言うと、ワインレッドの古びた衣装に袖を通しました。
そうです。あなたがサンタです。残り1日で煙突に社内サービスをデプロイしましょう!
(ここでいい感じのBGMを再生してください)
本記事の目的
以降では一例として、実際にサンタから業務委託をうけた筆者が煙突(Dokku)にプレゼント(PHPアプリケーション)をデプロイする際に失敗した点を紹介します。
なお、プレゼントはLaravel 5というフレームワークを利用して開発しました。(主題的に PHPにすればよかった)
これを読んだみなさんは失敗しない世界線へ……!
仮定していること
環境
- Dokkuのインストールは終わっていて、デプロイもできる。
- Laravel 5を使ったプロジェクトをデプロイしようとしている。
- サーバはnginxを使用する。
表記
- 山括弧(<>)がついたものは、自分のプロジェクトで使う文字列に適宜置換してください。その際に山括弧は削除してください。
- あなたのdokkuをホストしているサーバの名前を
your.dokku.domain
とします。
参考:dokkuのバージョン確認方法
ssh dokku@your.dokku.domain version
0.3.21
DokkuにLaravelのプロジェクトをデプロイする際にハマったポイント
単純にデプロイするとNode.jsアプリ扱いになる
PHPプロジェクトをデプロイする際にはいろいろ注意点があります。
Laravelのプレーンなプロジェクトをデプロイしようとすると次の結果が出ます。
git push dokku <deploy branch>
(略)
-----> Node.js app detected
デフォルトだとnode.jsのプロジェクトだと勘違いされてしまいます。
rootにcomposer.json
があるとPHPのアプリとみなしてくれるが、下位の階層にpackage.json
が存在するとnodeのアプリだとみなされるようです。これはHerokuでも同じみたい。
参考:HerokuでPHPを使うときに気を付けるところ - Qiita
解決策:PHPのプロジェクトとしてデプロイする
Buildpacksを使う。これはアプリケーションインストール時にサーバの設定を指定できるHerokuの仕組みです。
DokkuはHerokuのbuildpackをサポートしています。
Dokku supports deploying applications via Heroku buildpacks with Herokuish or using a project's dockerfile.
Dokku - The smallest PaaS implementation you've ever seen
heroku公式のPHP向けビルドパックheroku/heroku-buildpack-phpを使う。
pauldub/dokku-multi-buildpackをインストールし、プロジェクトのルートに.buildpacks
というファイルを作成し、中にGitHubのURLを書けば自動的に読み込まれる。
https://github.com/heroku/heroku-buildpack-php
豆知識:「Dokku PHP」で調べると一番上に出てくるリポジトリは2015年11月30日現在うまく機能しない
bobmaerten/dokku-buildpack-phpは罠で、途中で以下のようにエラーを吐いてコケる。
そもそもPHP5.6にも対応していないし不安を煽る。
remote: /tmp/buildpack3k4mD/bin/compile: line 270: /app/bin/jq: No such file or directory
remote: ! Script error in /tmp/buildpack3k4mD/bin/compile on or near line 270
勝手にテストがつくられて失敗してデプロイも失敗する
再度dokkuにデプロイするとまた失敗します。
(略)
-----> Preparing runtime environment...
NOTICE: No Procfile, using 'web: vendor/bin/heroku-php-apache2'.
Using release configuration from last framework (PHP).
-----> Discovering process types
Procfile declares types -> web
-----> Releasing <App name>...
-----> Deploying <App name>...
-----> Running pre-flight checks
For more efficient zero downtime deployments, create a file CHECKS.
See http://progrium.viewdocs.io/dokku/checks-examples.md for examples
CHECKS file not found in container: Running simple container check...
-----> Waiting for 10 seconds ...
remote: App container failed to start!!
=====> <App name> container output:
No dyno detected; using defaults for 1X...
4 processes at 128MB memory limit.
Starting php-fpm...
Starting httpd...
=====> end <App name> container output
remote: /usr/local/bin/dokku: 52 行: 18907 強制終了 dokku deploy "$APP"
(略)
解決策:CHECKSファイルを自作する
どうもpre-flight checksというものが自動で作られて、失敗しているようです。エラーメッセージに出ているリンクを見ながら自作します。プロジェクトのルートにCHECKS
というファイルをつくり、適当なテストを書きます。
WAIT=5
以上のファイルを作成すると正常にデプロイすることができました。お疲れ様でした。
dokku上でコマンド実行したら"cannot enable tty mode on non tty input"とかいわれる
出力結果が表示できない。
解決策:-tオプションをつけて実行する
The -t is used to request a pty.
Dokku - The smallest PaaS implementation you've ever seen
Dokku上で作ったアプリケーションの環境変数の設定をしたい
必要があれば、アプリ固有の環境設定を追加することができます。
ssh dokku@your.dokku.domain config:set <アプリ名> ENV=development
DokkuでDBをmigrationしたい
もしDBを使ったアプリケーションを作る場合、Dokku上でDBの設定をしなければなりません。やってみましょう。
DBを作成する
ssh dokku@your.dokku.domain postgresql:create <App name>
出力結果
PostgreSQL container created: postgresql/<App name>
Host: IP_ADDRESS
Port: PORT
User: 'user'
Password: 'password'
Database: 'db'
Url: 'postgres://user:password@IP_ADDRESS:PORT/db'
このDBの設定を参考にLaravel側の設定ファイル(.env)を書き換えます。
DB_CONNECTION=pgsql
DB_HOST=IP_ADDRESS
DB_DATABASE=db
DB_USERNAME=user
DB_PASSWORD=password
さらに、Laravel側のconfig/database.phpで利用するポートをPORT
に変更します。.envにDB_HOST=IP_ADDRESS:PORT
などとしても動かないので注意。
DBの設定を確認する
既にDBがある場合、以下のコマンドで同様の項目を確認することができます
DB一覧を取得
ssh -t dokku@your.dokku.domain postgresql:info
DBの詳細を取得
ssh -t dokku@your.dokku.domain postgresql:info <DB name>
DBに初期値を設定したい
LaravelのSeederクラスをつくっておけば、artisanコマンドで初期値を設定することができます。
Seederクラスの作り方:Database: Seeding - Laravel - The PHP Framework For Web Artisans
ssh -t dokku@your.dokku.domain run <App name> "php artisan migrate:refresh --seed"
Rolled back: 2014_10_12_100000_create_password_resets_table
Rolled back: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Seeded: UsersTableSeeder
Connection to your.dokku.domain closed.
初期値が適切に設定できたか確認する
PHP artisanを使ってDBに登録されたユーザを確認する
ssh -t dokku@your.dokku.domain run <App name> "php artisan tinker \<App name>\User::all()"
正常に初期値が設定されていればこれでその値が出力されます。
その他の設定
デフォルトだとrootのURLがindex.php
になりますが、your.domain.name/でindex.phpにアクセスして欲しいので、nginxの設定を書き換えています。
これらのDokkuに関連する設定ファイルはGistで公開しています。