Deploying a Rails 6 app to DigitalOcean’s New ‘Apps’ Feature

Allene Norton
7 min readDec 28, 2020
DigitalOcean.com deploy description

I recently had to navigate deploying a Rails 6 app to DigitalOcean for a contract, and as a relatively new developer, there were a few things that didn’t come intuitively or that weren’t mentioned in the documentation that I felt could use a little explaining. At Flatiron, I deployed my final project using Heroku + Netlify, but that was a Rails API back-end with a separate repository for a React front-end. I didn’t think things would be too different for a Rails-only app, but it wasn’t as simple as I had though it would be. I’ll walk through my experiences here in the hopes it may help other inexperienced developers.

Initial Deployment

The first thing I tried was deploying the app as-is. I connected my GitHub repo for the project and clicked ‘Deploy’. I knew it wouldn’t be that easy, and it definitely wasn’t. I didn’t realize that I would need to set up a managed database with DigitalOcean to handle my Postgres database within the Rails app. I tried to set one up separately, outside of the DigitalOcean Apps feature, but that took a lot of reading and troubleshooting and ultimately didn’t work out (because I was doing it the wrong way). I tried setting up a Droplet, but that wasn’t really what I wanted to do to either and, again, was pretty complicated. I knew I should be able to deploy just using the Apps feature, but I wasn’t sure how, so I started researching and learned quite a bit.

Troubleshooting a Local Production Environment

Rails Environments

The great thing about Rails 6 is that there are a lot of options for managing your environment. I had only worked in a development environment up to this point, and I had never tinkered with setting up the environment for production. There is a lot that goes into setting up the production environment, it turns out! I knew if I could get my production environment running locally, it wouldn’t be much of a stretch when it came time to deploy.

First, I tried starting my server locally in the production environment with the command ‘rails s -e production’, only to be met with a ‘We’re sorry, we don’t know what went wrong’ message from Rails. I checked the server logs as I usually do to debug, and was surprised to see nothing there. How was I supposed to figure out what went wrong?! “There must be some way to log the errors”, I thought. And there is.

Error Logs in Production

After a lot of reading on Stack Overflow, I figured out that I needed to set up some way to log the errors in production.rb in my Rails app. It was as simple as adding the line ‘ config.logger = Logger.new(STDOUT)’ in my production.rb file. This creates a new Logger instance that runs when the server is launched in the production environment. There is a block of code that asks if the line above is present that formats and configures the way the logs are presented. Once I added that line, I was able to see what was going wrong. In my case, I had some code for the SMTP info for our mailer that wasn’t reading the environment variables correctly. I went in and commented that out and was met with a new error upon restarting the server. My database wasn’t set up for the production environment, so I knew I needed to tackle that next.

Databases in Production

The app I was working on was an open-source app that connects volunteers to volunteer opportunities, and I was adapting it to the needs of the Sacramento-based non-profit I work for. The development and test databases were created and migrated with a simple ‘rails db:setup’ command, but the production database was not. I checked the database.yml file in Rails, and all of the environments and corresponding databases were listed, but the production database wasn’t being created. Some research led me to the command ‘rake db:create:all’. That command let me know that the development and test databases were already created, and that it created the production database as well. Sweet. Will it work this time? NO. Of course, I had to migrate! I ran the ‘rails db:migrate’ command as usual, and again I ran into the same problem I did with the first setup command. I figured out that I had to specify the production environment when running the migration command, like so: ‘rails db:migrate RAILS_ENV=production’. Once I did that, it worked! Well, sort of. As any dev knows, more errors always abound.

Webpacker in Production

On starting the server after fixing the database issue, I noticed that it wasn’t launching the page and was just hanging on ‘Webpacker: Compiling…’. I had to learn a lot about Webpacker when developing the app, which I’ll write more about in another piece. I learned how to start the webpack-dev-server in devlopment, and I knew there must be some issue with how Webpacker is running in production. I learned a bit about Rake tasks in the early days of the Rials module at Flatiron, but I didn’t use them much. To get the Webpacker running in production, I learned you need to run the command ‘rake assets:precompile’ before starting your production server. This precompiles all of your Webpacker assets so that Webpacker can compile them easily on the server launch. Once I did this, I was able to successfully launch the app in a local production environment. Success! Now, to figure out the deployment process.

Deploying to DigitalOcean Apps

Initial Setup

I deleted all of my experimentation with DigitalOcean Droplets and Apps, and started fresh. Luckily, it was much easier this time around. First, I connected the GitHub repository. Then, it read the code and recognized that I was launching a Rails 6 app. This time, I noticed an option to add a database on the app setup page.

Linking a Database

On the database setup page, it gave me options to add a dev-database or an existing managed database. I chose the dev-database option and followed the setup instructions which were simple and allowed me to name my database. Once I got through the initial setup, I reached a page that supplied some connection parameters. I recognized the parameters were similar to the parameters in my database.yml, so I went to the file and copied the supplied parameters into my production section in the YAML file. Once I committed and pushed the change to the repo, DigitalOcean Apps began auto-deploying my app again. I hoped this would be enough for the app to deploy, but once again I got stuck on database migration! I assumed it was a similar issue as when I tried launching in production locally, so I had to figure out how to migrate my production database through DigitalOcean.

Build Commands

Luckily, the DigitalOcean Apps feature allows you to set build and run commands for your app. From the DigitalOcean Apps docs:

The build command is the command-line statement that compiles your app component at build time. The build command should be geared towards installing all needed dependencies for your component to run, as every build starts from an environment that is empty other than the programming language runtime provided by the buildpack.

After reading this, I decided to try adding my ‘rails db:migrate RAILS_ENV=production’ command to my app’s build commands. The build command was run during the deployment and migrated my production database. Then, the deploy handled the specified run command, which defaults to launching the server on a specified port and in a Rails production environment. DigitalOcean let me know that my app was deployed successfully, but I wasn’t about to start celebrating until I saw my homepage in my browser. I was right to do so, because I was AGAIN met with the “We’re sorry…” message from Rails. Luckily, since I had configured my logger, I was able to see in the DigitalOcean server logs that the database needed a user to be seeded for Devise. So, I added the same ‘rails db:seed RAILS_ENV=production’ command I used locally to my build commands on DigitalOcean. Doing that triggered an auto-deploy, and this time, I was finally successful. Clicking the link to the hosted DigitalOcean app brought me to my homepage, and I was able to successfully navigate the app!

Conclusion

Since I am a new dev, I am not sure if the way I did things was 100% correct, but it worked. I am constantly realizing there is always so much more to learn, and I plan on doing even more research on Rails environments and Webpacker so that I am fluent in my understanding. I will say that I much prefer having a dedicated API server for my back-end and a separate front-end repository, as I feel it is a bit more flexible. I am not really a fan of building apps solely using Rails, but I think that is definitely a personal choice and I do see the benefits of an all-in-one framework. There are some things I want to work on regarding this app. I noted that some of my image assets are throwing file size warnings, and loading a bit slowly, so I want to pull them into Photoshop and see if I can’t fix that issue. I also need to add back in the SMTP info for the mailers, and set them up in DigitalOcean app’s environment variables, so that may be another future post topic. Otherwise, I was super excited that I was able to get the app hosted and running! I hope these struggles of mine can help inform anyone looking to use DigitalOcean’s Apps feature to deploy their application. I definitely recommend using this feature for deployment, as once I learned enough about what I was doing incorrectly, it was surprisingly easy to get everything working.

Thanks to DigitalOcean for their support, and you can check out the web application called Help With Covid here, which is the source code my organization, Community Connections Sacramento used for our application. I’ll add a link to the app here once it is finalized and connected to our domain. In the meantime, also check out our sister organizations Athens Help With Covid, New Haven Help With Covid, and City Help.

--

--

Allene Norton

Full stack developer and Flatiron graduate who recently made the jump from a career as a professional musician and audio engineer | Austin, TX