Migrating Rails App from self-hosted to Heroku

I am helping a Rails project to setup the environment. In the previous stage, they deployed the prototype to a self-hosted environment. In preparing a more scalable and easy to maintain environment, I suggest them to use Heroku. Thus, it starts the journey of migration.

Here are a list of things to work on:

  1. Deploy application to Heroku
  2. Run bower install
  3. Move image storage to S3
  4. Dump database to Heroku add-on Postgres

Deploy application to Heroku

This part is the easiest part. Heroku was first built as a way to easily deploy Rails application. Thus this is not a problem at all. In fact, over the years, Heroku has made the process further easier.

One setting I use now is the Continuous Deployment. I simply connect Heroku app to my GitHub account. It will add a post-commit hook to the GitHub project. I could set the branch I want to monitor. For instance, I want the deployment only happens if I have a merge to the `master` branch. This fits well to the Git-Flow strategy I use in development work.

In addition, if I want to deploy an ad-hoc application from the `develop` branch, I can still do it manually. It is not a must to setup the heroku git path. Yet, I will still set it, so that I can keep using heroku toolbelt with various commands.

Run bower install

As the project includes the use of Medium Editor library and some other frontend plugins which it uses bower to download the source codes to the application folder.

By default, Heroku provides a Ruby buildpack. In deploying the Rails application, it will fail as bower is not run and those frontend libraries are not available. I should apply a custom buildpack which will install bower in Heroku and then run `bower install` after each deploy.

All I need to do is to set the following link as buildpack URL in Heroku Settings.

git://github.com/qnyp/heroku-buildpack-ruby-bower.git

Move image storage to S3

The application stored all the images in the self-hosted environment. I shall move those images to S3. Assume I have created the S3 bucket and have the access and secret keys. The next thing to do is really copying the images.

As the project uses carrierwave to upload images, the image url is set in carrierwave config. It means after moving the images to S3, the URL would only change by replacing the domain to S3 URL.

In order to sync all the images to S3, I make use of a tool `s3cmd`, this is the command I use:

s3cmd sync uploads s3://<bucket-name> -P

The ‘-P’ option is needed to set all the images as publicly accessible. Otherwise, you will see an Access Denied. Being public, means the permission of each image in S3 is able to Open and Edit by Everyone in S3. You can see this information in S3 Dashboard.

Dump database to Heroku add-on Postgres

Last, but not least, is to dump the database from the old one to the new one. In general, it would mean running ‘pg_dump’ in the old database, which save a file of schema and data. I copied that from the server to local environment, and then if I am going to restore the exact file, I can run the following command:

heroku pg:backups restore ‘https://s3.amazonaws.com/<bucket-name>/dump.sql' DATABASE_URL

The restore process shall access the dump file from a publicly accessible URL. Typically, I can upload it to S3 and set it accessible by Everyone.

However, in this project, since it uses Medium Editor. It will save the image hard-coded link in the content. I shall grab the data file and replace all the image links to point to S3 path before the database restore.

Summary

That’s about it for now. That took me a whole afternoon to figure out, and make sure the application and data is now available in Heroku environment.