概要
- Google App Engine スタンダード環境で Ruby + Sinatra によるシンプルな Web アプリケーションを動かす
構成
- Google App Engine スタンダード環境
- Ruby 2.5
- Web アプリケーションフレームワーク: Sinatra 2.0.8
- テンプレートエンジン: Erb
- Web アプリケーションサーバ: Puma 4.3
Google App Engine スタンダード環境の Ruby はベータ版
現時点(2020年2月9日現在)ではまだベータ版の状態。
ベータ版になったのは2019年8月。
Ruby support comes to App Engine standard environment | Google Cloud Blog
Ruby is now Beta on App Engine standard environment, in addition to being available on the App Engine flexible environment.
Google App Engine Ruby 2.5 Standard Environment documentation
ベータ版
この機能はプレリリース版の状態で、変更やサポート制限が行われる可能性があります。
ソースコード
ファイル一覧
├── Gemfile
├── Gemfile.lock
├── app.rb
├── app.yaml
├── config.ru
├── public
│ └── images
│ └── icon.png
└── views
├── error.erb
└── hello.erb
Gemfile
sinatra-contrib は Sinatra Reloader などを使うために必要。
source 'https://rubygems.org'
gem 'puma'
gem 'sinatra'
gem 'sinatra-contrib'
Gemfile.lock
bundle install で生成された Gemfile.lock ファイル。
GEM
remote: https://rubygems.org/
specs:
backports (3.16.0)
multi_json (1.14.1)
mustermann (1.1.1)
ruby2_keywords (~> 0.0.1)
nio4r (2.5.2)
puma (4.3.1)
nio4r (~> 2.0)
rack (2.1.2)
rack-protection (2.0.8.1)
rack
ruby2_keywords (0.0.2)
sinatra (2.0.8.1)
mustermann (~> 1.0)
rack (~> 2.0)
rack-protection (= 2.0.8.1)
tilt (~> 2.0)
sinatra-contrib (2.0.8.1)
backports (>= 2.8.2)
multi_json
mustermann (~> 1.0)
rack-protection (= 2.0.8.1)
sinatra (= 2.0.8.1)
tilt (~> 2.0)
tilt (2.0.10)
PLATFORMS
ruby
DEPENDENCIES
puma
sinatra
sinatra-contrib
BUNDLED WITH
2.1.4
app.rb
メイン処理をするファイル。
require 'sinatra'
require 'sinatra/reloader' if development?
helpers do
# HTML エスケープ用にエイリアスを作成
include Rack::Utils
alias_method :h, :escape_html
end
# 404 Not Found 時
not_found do
@error_message = 'Page Not Found'
erb :error
end
# エラー発生時
error do
@error_message = h env['sinatra.error'].message
erb :error
end
# Hello メッセージ表示ページ
get '/hello/:message?' do
# q パラメータがあるときはエラーを発生させる
raise params[:q] if params[:q]
# Ruby のバージョンをセット
@ruby_desc = RUBY_DESCRIPTION
# メッセージをセット
if params['message'] != nil
@message = params['message']
else
@message = 'Hello, world!'
end
# 環境情報を取得
env = {
:dev => settings.development?,
:prod => settings.production?,
:test => settings.test?
}
# HTML を表示
erb :hello, :locals => env
end
app.yaml
Google App Engine 用の設定ファイル。
Google App Engine スタンダード環境でサポートされている Ruby のバージョンは 2.5。
runtime: ruby25
# アプリケーション起動エントリポイント
entrypoint: bundle exec rackup -s Puma -p $PORT
# 第2世代ランタイム, インスタンスクラス F1, メモリ制限 256MB, CPU制限 600MHz
instance_class: F1
# インスタンス数のオートスケール設定
automatic_scaling:
min_idle_instances: automatic
max_idle_instances: 1
min_pending_latency: 3s
max_pending_latency: 5s
max_concurrent_requests: 5 # 許容する同時リクエスト数(指定できる最大値は80)
target_cpu_utilization: 0.95 # インスタンス立ち上げトリガーなCPU負荷率(0.5から0.95の間で指定)
max_instances: 1 # 最大インスタンス数
# 環境変数
env_variables:
RACK_ENV: production
# 静的ファイル配信用設定
handlers:
- url: /images
static_dir: public/images
secure: always
config.ru
rackup コマンド用に config.ru を用意する。
require './app'
run Sinatra::Application
views/error.erb
エラーページ用 HTML テンプレート。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Error page</title>
</head>
<body>
<p><%= @error_message %></p>
</body>
</html>
views/hello.erb
ページ用 HTML テンプレート。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, World!</title>
</head>
<body>
<p><%= h @message %></p>
<p>Ruby: <%= h @ruby_desc %></p>
<p>development?: <%= dev %></p>
<p>production?: <%= prod %></p>
<p>test?: <%= test %></p>
<p><img src="/images/icon.png" alt="icon" title="icon"></p>
</body>
</html>
ローカルでサーバを起動
bundle install で環境を構築
bundle install コマンドで Gemfile.lock または Gemfile に記載してあるパッケージがインストールされる。
development 環境
開発時に使う起動方法。
RACK_ENV=development を指定する。
エラーメッセージなどがわかりやすく Web ページ上に表示される。
$ RACK_ENV=development bundle exec rackup -s Puma
Puma starting in single mode...
* Version 4.3.1 (ruby 2.5.7-p206), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: development
* Listening on tcp://127.0.0.1:9292
* Listening on tcp://[::1]:9292
Use Ctrl-C to stop
production 環境
動作確認時に使う起動方法。
RACK_ENV=production を指定する。
$ RACK_ENV=production bundle exec rackup -s Puma
Puma starting in single mode...
* Version 4.3.1 (ruby 2.5.7-p206), codename: Mysterious Traveller
* Min threads: 0, max threads: 16
* Environment: production
* Listening on tcp://0.0.0.0:9292
Use Ctrl-C to stop
Google App Engine にデプロイ
事前にデプロイ先のプロジェクトの作成や gcloud コマンドでアカウント認証などをしておく(課金設定等のためCUIコマンドだけでは完結しないと思われる)。
参考: Quickstart for Ruby in the App Engine Standard Environment
$ gcloud auth login
$ gcloud projects create [YOUR_PROJECT_ID] --set-as-default
$ gcloud app create --project=[YOUR_PROJECT_ID]
$ gcloud config set project [YOUR_PROJECT_ID]
$ gcloud config list
gcloud app deploy コマンドで Google App Engine にデプロイする。
$ gcloud app deploy
Google App Engine のサーバにアクセス
200 OK
$ curl -i "https://simple-sample.appspot.com/hello/こんにちは世界<>\"'&"
HTTP/2 200
content-type: text/html;charset=utf-8
vary: Accept-Encoding
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-cloud-trace-context: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;o=1
date: Sun, 09 Feb 2020 04:20:35 GMT
server: Google Frontend
content-length: 379
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hello, World!</title>
</head>
<body>
<p>こんにちは世界<>"'&</p>
<p>Ruby: ruby 2.5.7p206 (2019-10-01 revision 67816) [x86_64-linux]</p>
<p>development?: false</p>
<p>production?: true</p>
<p>test?: false</p>
<p><img src="/images/icon.png" alt="icon" title="icon"></p>
</body>
</html>
404 Not Found
$ curl -i https://simple-sample.appspot.com/
HTTP/2 404
content-type: text/html;charset=utf-8
vary: Accept-Encoding
x-cascade: pass
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-cloud-trace-context: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
date: Sun, 09 Feb 2020 04:14:11 GMT
server: Google Frontend
content-length: 133
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Error page</title>
</head>
<body>
<p>Page Not Found</p>
</body>
</html>
500 Internal Server Error
$ curl -i https://simple-sample.appspot.com/hello/?q=テスト用エラー
HTTP/2 500
content-type: text/html;charset=utf-8
x-xss-protection: 1; mode=block
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-cloud-trace-context: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX;o=1
date: Sun, 09 Feb 2020 04:14:37 GMT
server: Google Frontend
content-length: 140
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Error page</title>
</head>
<body>
<p>テスト用エラー</p>
</body>
</html>
画像へのアクセス
app.yaml の handlers で静的配信指定しているのでレスポンスヘッダに Cache-Control や Expires が設定される。
$ curl -i https://simple-sample.appspot.com/images/icon.png
HTTP/2 200
date: Sun, 09 Feb 2020 04:14:50 GMT
expires: Sun, 09 Feb 2020 04:24:50 GMT
etag: "XXXXXX"
x-cloud-trace-context: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
content-type: image/png
server: Google Frontend
cache-control: public, max-age=600
content-length: 18136
age: 0
alt-svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000