LoginSignup
25
17

More than 3 years have passed since last update.

Google App EngineのRuby/スタンダード環境を試してみた

Posted at

はじめに

Google App Engineスタンダード環境でRubyがサポートされました。
https://cloud.google.com/appengine/docs/standard/ruby/?hl=ja
サポートされたんだよね、本記事執筆時点(2019/9/9)で「ベータ版です」とか書いてあるけどドキュメントが追い付いてない?

まあそれはともかくGAEスタンダード環境とあれば私の出番だということで(?)、GAEスタンダード環境でのRubyの使い方について見ていきたいと思います。見ていくポイントは以下の3点です。

  • 依存ライブラリはどうやって入れる?
  • DatastoreとかのGCPサービス使うAPI(Rubyライブラリ)ある?
  • Rails動かせる?

依存ライブラリの指定方法

まずは依存ライブラリをどうやって入れるのかです。
結論から先に言うとGemfileを書いておけば普通にBundlerを使ってインストールしてくれます。ここら辺はPythonやNode.jsと同じですね。

Quickstartで紹介されているHello World app(Sinatraで書かれています)を見るとGemfileで依存ライブラリが指定されていることが確認できます。

起動方法と待ち受けるポート

起動するプログラムはapp.yamlにentrypointで指定します。先のHello World appの場合は以下のようになっています。

app.yaml
runtime: ruby25
entrypoint: bundle exec ruby app.rb

このアプリの場合、Sinatraデフォルトのサーバ起動が行われ、Sinatraしか入れてないので標準ライブラリのWEBrickがサーバとして使われます。

production環境でWEBrickはあかんやろm9(^Д^)プギャー、という場合はすぐ横にHello WorldアプリをPuma(Rack)使って起動している例があります1
こちらを見ると待ち受けるポートは環境変数PORTで渡されてくることがわかります2。またこの例を見るとstaticファイルはGAEにserveさせる方法もわかります。
https://github.com/GoogleCloudPlatform/ruby-docs-samples/tree/master/appengine/standard-hello_configs

GCPサービスのAPI

Rubyがスタンダード環境で動かせると言ってもGCPの各種サービスにアクセスできなければ意味がない、まあ究極的にはWeb APIなので自力で書くことはできますがライブラリがあるなら使いたい。
はい、あります。これも公式サンプルに用意されています。フレキシブル環境使ってますがスタンダード環境を使うように直すのは容易です。
https://github.com/GoogleCloudPlatform/ruby-docs-samples/tree/master/appengine/datastore

app.yamlを以下のように直してgcloud app deployするだけです。

app.yaml
runtime: ruby25
#env: flex
entrypoint: bundle exec ruby app.rb

Railsの動かし方

SinatraはいいからRailsはどう動かすんだという声が聞こえてきそうですが、あらかじめ言っておくと結構大変です(笑)

Railsなんだから当然データベース使いますよね。
ここで「無課金で動かす」は諦めてください。
GCPにはCloud SQLというRDBMS(MySQL or PostgreSQL)動かすサービスが提供されていますがお金かかります。
Cloud SQLはGCEのインスタンス立ててDB専用にするみたいな感じ、値段はそこそこのお値段になります3

現時点ではフレキシブル環境のサンプルしかありません。スタンダード環境とフレキシブル環境の違いがわかっていればこれを参考にして動かすことは可能です。ということで以下その方法です。
https://cloud.google.com/ruby/rails/using-cloudsql-postgres

Rails / GAEスタンダード環境デプロイ方法

基本的に上記のチュートリアルに沿って話を進めていきます。

1. Cloud SQLインスタンスを作成する

先に説明した、Railsで使うデータベースを作成します。
インスタンス作成→データベース作成の順番になります。インスタンス作成時のpostgresユーザパスワードはもちろん覚えておくように。

2. Railsアプリの用意

私は普段Windowsで生きてるのですがデプロイできるバージョン構成が作れなかったので結局Cloud ShellでRailsアプリを作成・デプロイを行いました。
2019/9/9時点でRailsは6.0.0が入っているのですが6.0.0で作ってデプロイしたところ動かせなかった4ので以下のようにGemfile書いて5.2.3入れて5.2.3でアプリを作りました。

Gemfile
source 'https://rubygems.org'

gem 'rails', '5.2.3'
$ bundle install
$ bundle exec rails new cat_sample_app

以降、scaffoldしてroute.rbを設定するところは普通のRailsアプリ通りです。

3. GAE用の設定を書く

チュートリアルにあるようにpgとappengineのgemを足します。

$ bundle add pg
$ bundle add appengine

次にconfig/database.ymlのproductionを設定します。「インスタンス接続名」はコマンドか管理画面で確認できます。
パスワード直書きとかm9(^Д^)プギャーという方は環境変数DATABASE_URLで指定できると思うので(未検証)、そちらで指定してください。ちなみに「/cloudsql/インスタンス接続名」とあるように接続はUNIXドメインソケットで行われます(実際にApp EngineとDBが同じマシン内で動くわけではないと思うのですが)

config/database.yml
production:
  adapter: postgresql
  encoding: unicode
  pool: 5
  timeout: 5000
  username: "postgres"
  password: "パスワード"
  database: "cat_list_production"
  host:   "/cloudsql/インスタンス接続名"

チュートリアルにはありませんが(フレキシブル環境だと必要ない?)、これ以外にGemfileでRubyのバージョンを指定しているのをコメントアウトする必要がありました。
スタンダード環境は2.5.5なので、それ以外が書いてあるとデプロイ時にエラーになります。

Gemfile先頭
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

#ruby '2.6.3'

4. app.yamlを書く

チュートリアルに書かれているのはフレキシブル環境用のapp.yamlなので、これをスタンダード環境用に書き換えます。cloud_sql_instancesは必要ありません。

app.yaml
entrypoint: bundle exec rackup --port $PORT
runtime: ruby25

env_variables:
  SECRET_KEY_BASE: 「bundle exec bin/rails secret」の結果

5. .gcloudignoreを用意する

.gcloudignoreはデプロイしないファイルを指定するものです。これがない場合ドット始まりのファイルが送信されないという仕様?なのかsprocketsが正常動作しませんでした。

.gcloudignore
#!include:.gitignore
.git
.gitignore

!/public/assets

6. デプロイ(まだ終わりじゃないよ)

App Engineアプリを作り、アセットをコンパイルし、デプロイします。チュートリアルでは--no-promoteが付いていますが初デプロイの場合は結局それがメインのバージョンになるので違いはありません。

$ gcloud app create
$ bundle exec bin/rails assets:precompile
$ gcloud app deploy

7. データベースマイグレーション

上で一度デプロイをしているのはCloud Buildのサービスアカウントを作るためです。Cloud Buildとは何ぞやということは末尾の参考記事をご参照ください。

プロジェクトIDだったりプロジェクト番号だったりでうっとうしいですが以下のようにして必要な権限を追加します。

$ gcloud projects add-iam-policy-binding プロジェクトID --member=serviceAccount:プロジェクト番号@cloudbuild.gserviceaccount.com --role=roles/editor

さてとデータベースマイグレーションです。ここで先ほど入れたappengine gemが出てきます。
何をしているのかというと、テンポラリのapp.yamlを作って、entrypointに指定されたコマンドを書いて実行して、デプロイされたテンポラリのバージョンを消すという超絶なことがされています(笑)
このappengine gemが2.5で追加されたメソッド使っているので5、デプロイする環境のRubyも2.5以上である必要があります。

$ bundle exec rake appengine:exec -- bundle exec rake db:migrate

以上でデプロイは終了です。

二回目以降のデプロイ

二回目からは以下のコマンドを打てばデプロイが行えます。

$ bundle exec bin/rails assets:precompile
$ gcloud app deploy
$ bundle exec rake appengine:exec -- bundle exec rake db:migrate

おわりに

以上、Google App Engineのスタンダード環境でRubyを使う場合を見てきました。
Node.jsと大体同じでした(広く使われている依存ライブラリの指定方法、起動プログラムは自分で指定、ポートは環境変数PORT)

触ってみた感想としては、Rails動かすのは特に無課金で使うつもりだったのなら諦めてHerokuを使え、GAE使うならDBはDatastore使ってフレームワークはSinatra使うのが楽だぞというところです。

参考というかこちらもどうぞの記事

Google App EngineのNode.js/Standard環境の仕組みについて調べてみた
Node.jsがスタンダード環境にデプロイされる仕組み(デプロイプロセスは何を行っているのか)を調べた記録です。Rubyでも大体同じ仕組みでデプロイが行われています。

GoogleAppEngineでDjangoを3年ほど動かしてわかったこと
思い出話ですがこの記事と関連する箇所としてはCloud SQLの話があります。


  1. ここで起動しているアプリサーバが直接リクエストを受けるわけではなくロードバランサがいてリクエストがフォワードされるわけですが、まあWEBrickよりはPumaの方がいいですよね。 

  2. 素のSinatraの場合は環境変数PORTを見ているのでentrypointで指定はされていませんでした。 

  3. MySQLはインスタンスのスペックを落とせますがPostgreSQLは最低スペックがメモリ3.75GBのようです。asia-northeastだと$64/月かかります。 

  4. tmp/pids/server.pidがない、ていうか、tmp/pidsがないというエラー。もう少し調べれば動かせるのかもしれませんが。 

  5. 具体的にはSecureRandom.alphanumeric。他にもあるかもしれません。 

25
17
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
17