Rails
GAE
GoogleCloudPlatform
CloudStorage
cloudsql

RailsアプリをGAEにデプロイしCloudSQL, CloudStorageと連携させる

最近、GCPの注目度が高まってきていると感じています。

機能が多いAWSよりもより手軽にできるという点やkubernetesの恩恵を受けやすいのが魅力的だと思います。さらに、個人的に今後開発にGo言語を使う新規プロジェクトが増えいくと思っていて、その際にGoogle発のものは相性よさそうだなーとぼんやり思ったりしています。

インフラを本格的に運用した経験はありませんが、簡単にRailsアプリをGAE(Google App Engine)にデプロイしてみたのでその方法をメモしておこうと思います。

GCP内にプロジェクトを作成し、gcloudをインストールしてある状態であることが前提です。

GCPの公式ドキュメントをよめば問題なくデプロイできるので、注意点や重要なポイントのみを中心に記していきます。

App Engineにデプロイ

デプロイしたいアプリのディレクトリ直下にapp.yamlを用意します。

app.yaml
runtime: ruby
env: flex
entrypoint: bundle exec rackup --port $PORT

そして、デプロイしたいアプリとGCPとの連携が終わっていれば、こちらのコマンドを打つだけでApp Engineにデプロイができます。

$ gcloud app deploy

環境変数をセットしたい

環境変数があるプロジェクトがほとんどだと思います。
app.yamlに環境変数を書くことでGAEに環境変数を渡せます。

app.yaml
runtime: ruby
env: flex
entrypoint: bundle exec rackup --port $PORT
env_variables:
  SECRET_KEY_BASE: [YOUR_SECRET_KEY_BASE]

また、app.yamlはgit管理したいけど、環境変数はgit管理したくない場合はyamlファイルをもう一つ用意し、app.yamlによみこませ、そのyamlファイルをgitignoreさせればいいかと思います。

app.yaml
runtime: ruby
env: flex
entrypoint: bundle exec rackup --port $PORT
includes:
- secret.yaml
secret.yaml
env_variables:
  SECRET_KEY_BASE: [YOUR_SECRET_KEY_BASE]
.gitignore
secret.yaml

ログがみたい

ログがみたい場合は2つ方法があります。

  1. ターミナル上でgcloud app logs readを打ってログをみる方法
  2. GCP上のログビューワーでログをみる方法

すでにDockerfileが存在する

GAEにデプロイしたアプリはDocker上で動くためDockerfileがプロジェクト直下にあるとRuby runtimeでデプロイができません。その場合はCustom runtimeでのデプロイになります。

app.yaml
runtime: custom
env: flex
entrypoint: bundle exec rackup --port $PORT

もしRuby runtimeでデプロイしたい場合は、DockerfileをDockerfile-devなどに置き換えておくといいかもしれません。

デプロイに使用するDockerfileが知りたい

こちらにGCPで使用されるRubyのbase imageが確認できます。

このbase imageを用いて新しいDockerfileを作ることもできます。

Dockerfile
FROM l.gcr.io/google/ruby:latest

CloudSQLと連携させる

今回はGCP上でMySQLでインスタンスを作成し、アクセスに使うユーザーやデータベースを作成します。

まず、database.ymlを変更します。

database.yml
production:
  <<: *default
  database: [YOUR_DATABASE]
  username: [YOUR_USERNAME]
  password: [YOUR_PASSWORD]
  socket: /cloudsql/[YOUR_INSTANCE_CONNECTION_NAME]

[YOUR_INSTANCE_CONNECTION_NAME]はGCP上で確認できますが、作成したプロジェクトの名前がわかれば以下のコマンドでもわかります。

$ gcloud sql instances describe [YOUR_PROJECT_NAME]

また、app.yamlは以下のように変更します。

app.yaml
runtime: ruby
env: flex
entrypoint: bundle exec rackup --port $PORT
beta_settings:
  cloud_sql_instances: [YOUR_INSTANCE_CONNECTION_NAME]
includes:
- secret.yaml

APIを有効にするのも忘れずに行いましょう。APIを有効にしないと、Google::Cloud::PermissionDeniedErrorが発生します。

migrationを実行する

CloudSQL上でのmigrationの実行はgem 'appengine'にて行えます。

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

ちなみに、ridgepoleでもきちんとmigrationできました。

$ bundle exec rails appengine:exec -- bundle exec ridgepole -c config/database.yml -E production --apply -f db/schemas/Schemafile

MySQLのオプションを追加したい

データベースの文字コードをいじった時などに、オプションを設定したい時があるかと思います。
そういったときは、Cloud SQLフラグを使用するとMySQLのパラメータやオプションの指定内容を変更できます。

CloudStorageと連携させる

carrierwave, fogを使ってCloudStorageと連携させます。アクセスキーとシークレットキーを取得後、initialize以下にcarrierwave.rbを作成します。

carrierwave.rb
CarrierWave.configure do |config|
  config.fog_credentials = {
    provider: 'Google',
    google_storage_access_key_id: [YOUR_ACCESS_KEY],
    google_storage_secret_access_key: [YOUR_SECRET_ACCESS_KEY]
  }
  config.fog_directory = [YOUR_BUCKET_NAME]
end

あとは、uploader用のファイルにstorage :fogを追加すれば完了です。

終わりに

デプロイ時に少しエラーがでたりしましたが、意外とすんなりできました。

個人で開発したWebサービスなどでインフラを任せてしまいたい時に積極的に使っていけたらなと思っています。