Last time I finished writing the battleship server. The next step is to deploy it somewhere. I’m close to my first real deadline, Seattle.rb next Tuesday evening, so I’m taking the easy way out and deploying it on Google App Engine. In the future, I plan to write up a blog post for doing a Kubernetes deployment. I also hope to eventually port the logic to both Node.js and Python because I think the language comparison will be interesting.
I already had a GCP account and the GCP SDK installed on my computer. If you are following along at home there are instructions for these steps in the “Before You Begin” box on the Rails 5 on App Engine tutorial. Since the last time I talked about App Engine the Ruby Software Engineering team has released an App Engine Gem. This gives me some handy features for running rake tasks in production and automatically pulls in GCP’s monitoring tools for Ruby. To use it I have to add
gem "appengine" to my Gemfile and add
require "appengine" to my Rakefile.
As I established in the last post, I’m using Sinatra. I like that it is lightweight, but it means I have to do some configuration work. To run the app on App Engine I need a
config.ru file. I took a generic one from the Sinatra docs and put it at the root of my application.
I’m using PostgreSQL with ActiveRecord for the database. In the spirit of impending deadlines, I’m using managed PostgreSQL from CloudSQL. This way I don’t have to worry about firewall rules and networking between my web servers and my database.
I created a CloudSQL instance following the instructions in the Cloud SQL documentation. Then I created a user for my application. I called it rails because I always call my users rails. I only realized that was inappropriate (I’m using Sinatra) once I started writing this post out. I also created a static IP following the instructions under connecting using IP Addresses. I added the following to my database.yml file:
production: <<: *default database: "battleship_production" username: "rails" password: [PASSWORD GOES HERE] host: [YOUR DATABASE IP HERE] timeout: 5000
Using a static IP isn’t the best solution. There are a lot of security implications. I should be using the CloudSQL Proxy but I wanted something that would work quickly to prove my deployment. I can go back later and change how the application connects to the database.
To run the migrations using the appengine gem I need to add the following to my Rakefile.
Deploying The App
Deploying an application to App Engine for Ruby is simple, you just type
gcloud app deploy. The gcloud SDK will analyze your application and make some recommendations on the first run. The defaults are fine. It will use the defaults to write an
app.yaml file that looks like this:
The actual deployment may take a while. For me, deployments were taking around seven minutes. I wish they were faster and I know the team is working on it but that is something to keep in mind when deciding where to run your application.
Once the app is deployed you can run your migrations like this:
bundle exec rake appengine:exec -- bundle exec rake db:migrate
gcloud app deploy routes all traffic to the latest version of your application as soon as it is up and running. If you need your migrations to run before that version can handle traffic you can use the
gcloud app deploy --no-promote
Once your migrations are run, you can route traffic to the new version using the web UI.
My deployment to App Engine is at https://battleship-176302.appspot.com/ if you want to try it out yourself. Expect some instability over the next few weeks while I sort out details to make it usable for our workshop at Seattle.rb next week.
The code for this post is located here.