简体   繁体   中英

Rails migrations don't run on Google App Engine deploy

How do you run Rails migrations upon deploy to Google App Engine ( gcloud app deploy )?

I'm trying to deploy a Rails 5 (Ruby 2.3.1) app to Google App Engine using Cloud SQL. I followed the steps outlined in Google's Bookshelf tutorial and their GitHub repo for Cloud SQL to set up app.yaml and database.yml.

The deploy completes successfully and I'm able to view the landing page of my app, but when I go to the Sign In or Sign Up pages, I get a 500 error because the Users table hasn't been created.

Step 8 of the deploy log seems to mention asset precompile

Step 8 : RUN if test -d app/assets -a -f config/application.rb; then       bundle exec rake assets:precompile || true;     fi

But I don't see anything like db:create and db:migrate , which I need to run when I deploy.

FYI, I have run rake db:migrate and everything is working as expected on local.

Thanks!

You're correct that it isn't run after running gcloud app deploy . We also probably wouldn't want to run it from the containers, because there are several of them, and if we ran it on all of them then there would be a race condition in which sometimes some of the migrations would run twice, or perhaps one would run before another is finished. Therefore it makes sense to run them on the machine from which you are deploying. Fortunately, that's easy using the Google Cloud SQL Proxy (this assumes you're using Cloud SQL of course). See this link for documentation: https://cloud.google.com/sql/docs/mysql/connect-external-app#proxy

First, we set up the cloud SQL proxy itself (these are for Linux):

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 chmod +x cloud_sql_proxy.linux.amd64 sudo mv cloud_sql_proxy.linux.amd64 /usr/local/bin/cloud-sql-proxy

Then using gcloud , login and set the default project to the one you're currently working with (because the cloud SQL proxy uses the gcloud configuration to figure out how to connect):

gcloud config set project <your project name> # we don't want to deploy or connect to the wrong project! gcloud auth list # make sure you're dealing with the account you should be gcloud auth application-default login

The last step was necessary because I'm deploying from a Google Compute Engine VM, which already was logged in with a service account which didn't have the right credentials.

Then set up the cloud sql proxy socket directory. This works with Postgres as well. Just make sure that it's the same directory that your production config expects:

sudo mkdir /cloudsql sudo chown $USER /cloudsql

Then start the cloud sql proxy in another window or in the background:

cloud-sql-proxy -dir /cloudsql

Then run your deploy task and migration:

gcloud app deploy RAILS_ENV=production rake db:migrate

When I just set this up, I was frustrated by the fact that if you run the migration before your deployment (which takes a long time!), your site will be down. And if you run the migration after, then depending on how health checks are set up, it may detect that the new version is unhealthy. Since config.active_record.migration_error isn't set on production by default, I think the best option is to run the migration after the deploy unless you want to set up health checks in such a way that a health check endpoint will raise an exception if there are pending migrations. Then you could have your application move to the new version at the exact time when migrations are finished. However because of the nature of health checks running periodically, you'll still have a few seconds of downtime. The two-line script above (running the migrations after the deploy) is probably the best you can get without a whole lot more effort.

I am not familiar with Google App Engine, but a common approach is to run rake db:migrate comment as a part of deploy script.

I can see here that db:setup is executed as a part of setup script, did you commit/push to the Google App Engine updated version of db/schema.rb file? Based on it db:setup task should prepare an up-to-date version of the database.

I'm trying to do the same thing. So far, all I can find isthis page . You can also install the MySQL proxy on your local machine and then run your normal rake tasks (rake db:setup, which also runs db:seed), but this is much slower from my initial tests. Hopefully someone else has a better solution!

This is an old question but incase someone is looking for a solution like I was, simply run;

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

This worked for me!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM