DokkuにLaravel5のプロジェクトをデプロイする

  • 13
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

2015新卒の@kadoyauです。学部時代はロボットをいじり、院で音の情報処理をC++で書いていましたが、入社後は楽しくちょっと大きな金槌でWeb開発をしています。ヒヤッホォォォウ!PHP7は最高だぜぇぇぇぇ!!(ぐるぐる目)

サンタさんが来るお家をつくろう

:tada: :pizza: クリスマス:christmas_tree: :bell: もとい紅莉栖マスまであと2日になりました。
紅莉栖マスといえばサンタさん。今日は、あなたの会社に2日でサンタさんを呼ぶ方法をお教えしたいと思います。

煙突をビルドする

雇われサンタさんの収入は一定の時間内にデプロイできたプレゼントの価値で決まります。ということは、サンタさんはプレゼントを高速にデプロイするための煙突を有した家を好みそうです。煙突のない家にプレゼントをデプロイするのはめんどくさいですよね。
サンタさんを迎えるために、まず煙突をDokkuをつかってビルドしましょう!

Dokkuって何?

サービスをつくってデプロイするのは、ちょっと気合を入れないとめんどくさいものです。
サービスをつくりたいのに、それに必要なDBや環境の構築もいちいちしなくてはならない。サンタさんはプレゼント(サービス)をデプロイするのをためらうってわけです。

HerokuのようなPaaSが社内で使えると、環境構築はHerokuにまかせて、サンタさんはコードと設定を少し書くだけで気軽にデプロイできて便利です。
Dokkuを使うと、DockerベースのHerokuライクなPaaSを作ることができます。これが煙突です。まずは次の記事などを参考に、1日で煙突をビルドしましょう。

参考:DockerでミニHeroku!「Dokku」をさくらのクラウドで試す - さくらのナレッジ

これでサンタさんを呼ぶ準備は整いました。

プレゼントをデプロイする

翌朝目を覚ますと、サンタさんからの手紙(中身は業務委託を契約するための書類でした)があなたのもとへ届いていました。
「やれやれ、仕方ないな」あなたはそう言うと、ワインレッドの古びた衣装に袖を通しました。

そうです。あなたがサンタです。残り1日で煙突に社内サービスをデプロイしましょう!
(ここでいい感じのBGMを再生してください)

本記事の目的

以降では一例として、実際にサンタから業務委託をうけた筆者が煙突(Dokku)にプレゼント(PHPアプリケーション)をデプロイする際に失敗した点を紹介します。
なお、プレゼントはLaravel 5というフレームワークを利用して開発しました。(主題的に:cake: 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を書けば自動的に読み込まれる。

.buildpack
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というファイルをつくり、適当なテストを書きます。

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)を書き換えます。

.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で公開しています

この投稿は 第2のドワンゴ Advent Calendar 201523日目の記事です。