こんにちは! フィフス・フロア技術チームのチームリーダーnotozekiです。
先日、ついにGoogle App Engine(以下App Engine)のスタンダード環境でRubyがサポートされました🎉
Rubyのパパ、まつもとゆきひろさんも「感無量」とコメントしていますね☺️
スタンダード環境でのRubyのサポートはベータ版という扱いのようですが、すでに利用可能になっています。とういうことで、早速Rubyアプリをデプロイして試してみました🚀
ここで、App Engineとそのスタンダート環境について簡単に説明します。
App Engineとは、Googleが提供するWebアプリケーションの実行環境のPaaSです。
いくつかの言語向けのWebアプリ実行環境がはじめから用意されていて、開発者は自分のアプリのコードをApp Engineにデプロイするだけで、簡単にWebアプリをホストすることができます。
App Engineには「スタンダート環境」と「フレキシブル環境」の2種類の環境が用意されています。これらの環境の比較は、以下の公式ドキュメントが参考になります。
https://cloud.google.com/appengine/docs/the-appengine-environments
スタンダート環境は軽量なランタイムが特徴で、デプロイや起動が高速です。また、「ゼロにスケーリング」することが可能で、運用コストを抑えることができます。一方で自由度は低く、あらかじめ用意されているランタイムをカスタマイズしたり、自分の用意したイメージを使うことはできません。
Rubyのランタイムは、以前はスタンダート環境ではサポートされていませんでした。そのためRubyアプリをApp Engineにデプロイするにはフレキシブル環境を使うしかなかったのですが、このたびスタンダート環境でもRubyランタイムがサポートされたため、Rubyアプリでもスタンダード環境の恩恵が受けられるようになりました🙌
ちなみに、用意されているランタイムのRubyのバージョンは2.5のみとなっています(2019年9月現在)。
さて、ここから実際にRubyのスタンダート環境を触ってみます。
まずは公式のクイックスタートのドキュメントに従ってRubyアプリをデプロイしてみます。
https://cloud.google.com/appengine/docs/standard/ruby/quickstart
ちなみに、スタンダート環境には無料枠があるので、このクイックスタートのインスタンスを動かすだけなら料金は掛かりません。フレキシブル環境には無料枠が無いので、これはスタンダート環境を使えることの恩恵ですね✌️
App Engineを使うには、まずCloud SDKのインストールと、GCPのプロジェクトをセットアップする必要があります。Cloud SDKは以下の手順に従ってインストールします。
https://cloud.google.com/sdk/docs/
Cloud SDKがセットアップできたら、GCPのプロジェクトを新しく作ります。
$ gcloud projects create <プロジェクトID>
<プロジェクトID>
には、半角英数字とハイフン(-
)で構成された適当な名前を指定します。
余談ですが、この「プロジェクトID」は意外と曲者で、筆者は有効なプロジェクトIDを作るまでに以下のような罠を踏みました。
appengine
」という単語が含まれているとダメ(!?)特に最後のは「project_id contains prohibited words
」なんていうエラーが出て仰天しました。しかもどの単語が悪いのか教えてくれない😇(筆者はいろいろ試行錯誤してappengine
が原因だと突き止めました)
みなさまもプロジェクトIDの命名にはお気をつけください。
プロジェクトを作ったら、App Engineを初期化して使えるようにします。
ところで、App EngineはGCPプロジェクトにつき1つしかアプリを作れないという仕様になっています(*1)。したがって、ここではその「唯一のアプリ」を初期化することになります。なんとなく1つのGCPプロジェクトに複数のアプリを作れるようなイメージだったので、少し驚きました。
*1: 「サービス」という単位ではアプリを分割できます。詳しくはこちらなどを参照してください。
さて、App Engineの初期化は以下のコマンドで行います。
$ gcloud app create --project=<プロジェクトID>
アプリを作成するリージョンを聞かれるので、適当なリージョンを選びます。なお、このリージョンは後から変更することができないので注意してください。
最後に、支払いを有効化します。無料枠分しか使わないとしても、支払いの有効化は必要なようです。
https://console.cloud.google.com/projectselector/billing
これで準備は整いました。
公式で用意されているサンプルコードがあるので、それをデプロイしてみます。
https://github.com/GoogleCloudPlatform/ruby-docs-samples
まずはGitHubからリポジトリをcloneしてきましょう。リポジトリのappengine/standard-hello_world
ディレクトリの中に、Rubyのスタンダード環境向けのサンプルアプリのコードが入っています。
$ git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
$ cd ruby-docs-samples/appengine/standard-hello_world
サンプルアプリは、/
にアクセスするとHello world!
と表示するだけのごく簡単なものです。Sinatraで作られていました。
このアプリをApp Engineにデプロイしましょう。デプロイには以下のコマンドを使います。
$ gcloud app deploy --project=<プロジェクトID>
…たったこれだけです! 今回のアプリでは、初回のデプロイには2分ほどかかりました。2回目以降は1分程度でデプロイされます。
さて、デプロイされたアプリをブラウザで確認してみましょう。以下のコマンドを使うと便利です👌
$ gcloud app browse --project=<プロジェクトID>
やりました💪
bundle install
はどうなってる?ところで、このRubyアプリを動かすには、最初にbundle install
してSinatraなどの依存するGemをインストールする必要があります。しかし、自分で明示的にそれをする指定はとくにしていません。デプロイ時に自動的にbundle install
されると仮定して良いのでしょうか?
ドキュメントを探してもとくに記述が見つからなかったので、Cloud Build(*2)のビルドフェーズのログを見てみました。
*2: App Engineスタンダード環境では、デプロイ時にCloud Buildを使ってイメージがビルドされます(参照)。
Step #1 - "builder": [2019-08-30 11:41:21 INFO] => Running ruby25 build
Step #1 - "builder": [2019-08-30 11:41:21 INFO] => Installing bundle
Step #1 - "builder": [2019-08-30 11:41:21 INFO] ["bundle", "install", "--deployment", "--without=\"development test\""]
Step #1 - "builder": Fetching gem metadata from https://rubygems.org/........
Step #1 - "builder": Using bundler 1.17.3
Step #1 - "builder": Fetching diff-lcs 1.3
Step #1 - "builder": Installing diff-lcs 1.3
...(中略)...
Step #1 - "builder": Fetching sinatra 2.0.5
Step #1 - "builder": Installing sinatra 2.0.5
Step #1 - "builder": Bundle complete! 3 Gemfile dependencies, 13 gems now installed.
Step #1 - "builder": Gems in the groups "development and test" were not installed.
Step #1 - "builder": Bundled gems are installed into `./vendor/bundle`
Step #1 - "builder": [2019-08-30 11:41:26 INFO] => Checking for Rails sprockets
Step #1 - "builder": [2019-08-30 11:41:26 INFO] => Archiving app
Step #1 - "builder": [2019-08-30 11:41:26 INFO] ["tar", "cf", "/app.tar", "--transform", "s|^|srv/|rSH", "."]
Step #1 - "builder": [2019-08-30 11:41:26 INFO] => Archiving /.googleconfig
Step #1 - "builder": [2019-08-30 11:41:26 INFO] ["tar", "rf", "/app.tar", ".googleconfig"]
Step #1 - "builder": [2019-08-30 11:41:26 INFO] => Compressing archive
Step #1 - "builder": [2019-08-30 11:41:26 INFO] gzip < /app.tar > /app.tar.gz
Step #1 - "builder": [2019-08-30 11:41:26 INFO] => Creating destination image
...(中略)...
Step #1 - "builder": [2019-08-30 11:41:35 INFO] => Completed ruby25 build
このように、イメージのビルド時にbundle install
が実行されていました。したがって自動的にbundle install
されると仮定して良いようです。「Checking for Rails sprockets
」なんて記述があるのも気になります。Railsアプリの場合はrails assets:precompile
なんかもしてくれるのでしょうか? Railsでも試してみたいですね。
今回は、App Engineスタンダード環境にRubyアプリをデプロイして、その使用感を試してみました。
コマンド1つで手軽に、短時間でRubyのWebアプリをホストできる環境があるのはとても魅力的に感じました。実際、今回の調査ではプロジェクトIDに試行錯誤していた時間のほうが長かったくらいに、デプロイは一瞬でできました。無料枠があるので、「ちょっと試してみる」くらいのアプリを気軽に作れるのも嬉しいポイントです。
Rubyは言語自体の機動力はありますが、気軽にホストできる環境があまり無い印象でした。App Engineのスタンダード環境は、そこを補完してRubyにさらなる機動力を与える存在になり得ると感じます。
App Engine、ぜひ活用していきたいと思います!