Google App EngineでRailsのステージング環境と本番環境を構築したので、その方法をメモしておきます。
目次
database.ymlの編集
database.ymlにステージング環境用と本番環境用のDB情報をそれぞれ追加します。
・database.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ... staging: adapter: mysql2 encoding: utf8 pool: 5 timeout: 5000 username: sample_stg password: sample_stg_pass database: sample_stg socket: /cloudsql/sample_stg:asia-northeast1:sample_stg production: adapter: mysql2 encoding: utf8 pool: 5 timeout: 5000 username: sample_prod password: sample_prod_pass database: sample_prod socket: /cloudsql/sample_prod:asia-northeast1:sample_prod ... |
app.yamlの編集
GAEにデプロイするステージング環境と本番環境のapp.yamlファイルを作成します。
今回はGAEのスタンダード環境で構築しています。「RAILS_ENV=」で環境を指定します。
また、env_variablesで環境変数を指定することもできます。
・app-staging.yaml
1 2 3 4 5 | service: api--staging runtime: ruby25 entrypoint: RAILS_ENV=staging bundle exec rails s -e staging env_variables: SAMPLE_API_KEY: 'SAMPLE_STAGING_API_KEY' |
・app-production.yaml
1 2 3 4 5 | service: api--production runtime: ruby25 entrypoint: RAILS_ENV=production bundle exec rails s -e production env_variables: SAMPLE_API_KEY: 'SAMPLE_PRODUCTION_API_KEY' |
dispatch.yamlの作成
dispatch.yamlを作成し、ドメインとサービスを紐づけます。これでGAEのサービスにデプロイした際に、指定したURLに割り当てることができます。
・dispatch.yaml
1 2 3 4 5 | dispatch: - url: "*stg.sample.com/*" service: api--staging - url: "*sample.com/*" service: api--production |
dispatch.yamlが作成できたら、以下のコマンドでデプロイします。
1 | $ gcloud app deploy dispatch.yaml |
Railsプロジェクトをステージング環境と本番環境にそれぞれデプロイ
ここまで準備が完了したら、実際にRailsプロジェクトをそれぞれの環境にデプロイします。
■ステージング環境
デプロイする前にRailsアセットをコンパイルします。
1 | $ RAILS_ENV=staging bundle exec rails assets:precompile |
app-staging.yamlを指定してデプロイします。
1 | $ gcloud app deploy app-staging.yaml |
■本番環境
ステージング環境と同様、デプロイする前にコンパイルします。
1 | $ RAILS_ENV=production bundle exec rails assets:precompile |
app-production.yamlを指定してデプロイします。
1 | $ gcloud app deploy app-production.yaml |
デプロイする際に、target serviceがそれぞれの環境が選択できているか確認しておきましょう。
1 | target service: [api--staging] |
マイグレーション・シードの実行
マイグレーションとシードもそれぞれの環境に合わせて行いますappengineを使ってマイグレーションを実行します。
シード処理は時間がかかることがあるので、デフォルトの10分を30分まで伸ばしています。
■ステージング環境
マイグレーション処理
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate RAILS_ENV=staging |
シード処理
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--staging GAE_TIMEOUT=30m -- bundle exec rails db:seed RAILS_ENV=staging |
■本番環境
マイグレーション処理
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--production -- bundle exec rails db:migrate RAILS_ENV=production |
シード処理
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--production GAE_TIMEOUT=30m -- bundle exec rails db:seed RAILS_ENV=production |
① ハマりポイント「Errno::EROFS: Read-only file system @ rb_sysopen – /srv/db/schema.rb」
追加のマイグレーションファイルを作成し、実行するときにエラー発生。schema.rbが読み取り専用のため(スタンダード環境だから?)、実行できずにハマる。。
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate |
1 2 | [STDERR] rails aborted! [STDERR] Errno::EROFS: Read-only file system @ rb_sysopen - /srv/db/schema.rb |
解決策として、作成したマイグレーションファイルのバージョンを指定することで実行できました。
1 | $ bundle exec rake appengine:exec GAE_SERVICE=api--staging -- bundle exec rails db:migrate:up VERSION=20200401000000 |
1 2 3 4 5 6 7 | [STDOUT] == 20200401000000 AddColumnTests: migrating =================== [STDOUT] -- add_column(:tests, :test_id, :string, {:null=>true, :after=>:sample_id}) [STDOUT] -> 0.0461s [STDOUT] == 20200401000000 AddColumnTests: migrated (0.0462s) ========== [STDOUT] EXIT STATUS: 0 |
②ハマりポイント「Cannot run migrations because another migration process is currently running.」
マイグレーション対象のDBに接続した状態で、実行するとエラー発生。
1 2 3 4 | [STDERR] rails aborted! [STDERR] ActiveRecord::ConcurrentMigrationError: [STDERR] [STDERR] Cannot run migrations because another migration process is currently running. |
DBにログインし、以下のコマンドで処理中のプロセスの一覧を表示し、該当のプロセスを終了させて再度実行すれば通ります。
1 | $ SHOW PROCESSLIST |
以上、GAEでRailsのステージング環境と本番環境を構築する方法を紹介しました。