Seiichi Yonezawa

UbuntuでPuma-devの使いかた

あけましておめでとうございます。 今年の年末年始は特に外出の予定はなかったのでずっとコードを書いていた気がします。 このブログもRailsでの更新をやめてしまって以来、ほとんどRailsを書けていませんでした。 その反動からか、今年こそはRailsでも開発を継続していたいと思い何か書こうと思った次第です。

NOTE: 長々書いていますが、英語のREADMEを読めるレベルであれば直接読むことをおすすめします。

Puma-devとは

puma-dev replacement for pow and prax

その第一弾としてPuma-devを今回取り上げます。 Puma-devはRackアプリケーションをサーバは起動させずに、アドレスだけで切り替えられるというツールです。 例えばapple-railsbanana-railsというディレクトリがあったとして、アドレスバーにhttp://apple-rails.devを入力するとcd apple-rails && rails sをしなくてもサーバがレスポンスを返してくれるというものです。 そしてRailsサーバを起動しているわけでもないのでhttp://banana-rails.devではポートが重複することもありません。

NOTE: 現在公開されているPuma-dev v0.12ではTLDが.devではなく.testに変更されています。今回の投稿では.devに統一しますが、実際の挙動を試すときは適宜読み替えてください。

もともとはBasecampからPowというプロジェクトが公開されていました。 しかしこちらは既に開発終了しており、READMEファイルにはPuma-devを代替として使うようアナウンスされています。 また、PowはLinux環境で使うことができなかったためPuma-devに乗り換えない理由はないように思えます。

ここまではRubyを書いてきた人にとってはあまり新鮮味のない情報です。 実際のところ、Puma-devを使わなくても開発はできます。 しかし、Puma-devを紹介するのにはもうひとつの理由があります。

サブドメイン問題

先ほどのapple-rails.devというドメインを考えてみましょう。 通常のユーザはhttp://apple-rails.dev/にのみアクセスさせるとします。 そして、管理画面は一般公開せずにhttp://admin.apple-rails.devというドメインで分離したいとします。 この場合どのように開発すればよいでしょうか。

そこで登場するのがhttp://lvh.meというドメインです。 このドメインは簡単に言えば誰でも使えるlocalhostのようなもので、nslookup http://lvh.meすると自分のプライベートIPアドレスが返ってきます。 実はこれ、http://admin.lvh.meというように任意のサブドメインを指定しても結果は変わりません。 つまり、このアドレスを利用すれば上記の開発はできてしまうわけです。

しかし、このアドレスをどう捉えるかは自由です。 少なくともこのアドレスを利用することが危険だとは思いませんが、オフライン時は開発できません。 同様の理由でxip.ionip.ioも便利ですが、開発はいつでもどこでもローカルで行いたいものです。

Puma-devをインストールしよう

前置きが長くなりましたが、ここでようやくPuma-devに戻ります。 上記のサブドメインに加えて、powではできなかったHTTPSでの開発やActionCableの開発もできるみたいです。 macOSだとHomebrewで一発なのですが、我々LinuxユーザはREADMEにも書かれている通りインストールに一手間かかります。

NOTE: ちなみに今このブログはmacOSで書いてます。

$ uname
Linux
$ wget https://github.com/puma/puma-dev/releases/download/v0.12/puma-dev-v0.12-linux-amd64.tar.gz
$ tar xvf puma-dev-v0.12-linux-amd64.tar.gz
$ sudo install puma-dev /usr/local/bin
$ which puma-dev
/usr/local/bin/puma-dev

上記の流れはバイナリをダウンロードして、インストールしています。 ただし、このままではまだ使えませんので続いてdev-tld-resolverをインストールしてTLDを使えるようにしてみましょう。

$ sudo apt-get install build-essential git
$ git clone https://github.com/mnishihan/dev-tld-resolver.git
$ cd dev-tld-resolver/src && make
$ sudo make install

上記の方法はREADMEよりUbuntuのものだそうですが、nsswitch.confがサポートされているLinuxであれば動くと書かれています。 そこで今回はnsswitch.confについて少しだけ調べてみます。

nsswitch.confについて

The Name Service Switch file, /etc/nsswitch.conf, is used by the GNU C Library and certain other applications to determine the sources from which to obtain name-service information in a range of categories, and in what order. ネームサービススイッチファイル/etc/nsswitch.confは、GNU Cライブラリおよびその他の特定のアプリケーションによって、さまざまなカテゴリでネームサービス情報を取得するためのソースを決定するために使用されます。

とのこと。 で、今回は何をしているかというとここに先ほどのdev-tld-resolverを追加してあげるとOSがDNSに加えて自分で定義したTLDが使えるというわけ。

# /etc/nsswitch.conf
-hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4
+hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4 dev_tld

あとは先ほどのnsswitch.confにdev_tldを追加します。 これでnsswitchの設定は完了です。

NOTE: こうして調べるまではNSS Witchと読んでいました。

$ echo "DEV_TLD_DOMAINS=dev,test,puma" | sudo tee -a /etc/environment

そして/etc/environmentに対してDEV_TLD_DOMAINS=dev,test,pumaを追加します。 これは言うなれば自分のシェルのrcファイルに追加するのと変わりませんが、これならOS全体の挙動を変更できるみたいですね。 あまり使う意味合いもなさそうですが、長年謎だった/usr/games/usr/local/gamesはここに定義されていたわけです。 このあとPCを再起動してからping -c 1 http://foo.devを実行すると受信に成功するはずです。

80と443の割り当て

はやる気持ちを抑えきれずにpuma-devを実行してみても、画面上にはそれぞれ9280と9283というポートにサーバが割り当てられます。 我々が愛したPowはhttp://apple-rails.devというアドレスが使えたのですが、これがhttp://apple-rails.dev:9280ならなんだかPowに対する気持ちを捨てきれそうにありません。 そこで、ポート80および443に対するLinuxケーパビリティを追加します。

$ sudo setcap cap_net_bind_service=+eip /usr/local/bin/puma-dev
$ puma-dev -sysbind & # ヒント: fgを入力後にCtrl+Cで終了
$ cd ~/.puma-dev && ln -s /path/to/apple-rails apple-rails

このコマンドを使うことでpuma-devに1024以下のポート番号を割り当てられるようにできる仕組みです。 これで問題なくコマンドが起動できるか確認しましょう。 あとはPowのようにapple-railsのディレクトリにシンボリックリンクを作ってあげましょう。 上記の内容が正しくセットアップできれば無事に開通するはずです。

そのほか

最後にいくつか気になった点について触れています。

ログについて

rails sコマンドを使う利点は標準出力画面に親切なログが大量に表示されるところにあります。 しかし、Puma-devはリクエストをProxyしているので当然ながら標準出力というものがありません。 ディレクトリでtail -f log/development.logを実行すればいつもとなんらかわりない表示がされるはずです。

Webpacker、Sidekiqについて

Does Puma-dev support Rails' webpack integration?

Puma-devはあくまでRackアプリケーションのみを対象にしています。 つまり、Webpackなどのコマンドで起動するものに対してはRackサーバのラッパを書かなければなりません。 現時点ではこの回答に対して簡単な解決法はないと締めくくられているので今はスルーしています。 もし仮にできたとしてもWebpackサーバを再起動する方法も必要なので自分で書くのは何かと大変そうです。

デーモン化

Powのような使用感を求めるならばデーモン化していつでもサーバが起動している状態が好ましいです。 しかし逆に言えば常にポートが開いている状況になるので、当然ですがファイヤウォールの設定などを確認しておきましょう。 そういった諸々のことを考えるよりも先述のWebpackerと同様に手動で管理したほうがよいかもしれません。

投稿一覧