Google Cloud Run on Rails: a real life example (Part 4: going live!)

Laurent Julliard
Google Cloud - Community
7 min readMay 21, 2019

After going through Part 1, Part 2 and Part 3, here is the last installment of this series. This is where your application is actually going live in the wild Internet. 😅

Preparing Google Cloud Build

The mission of Cloud Run in life is to deploy and scale HTTP/S-driven workloads packed in containers. So let’s build a container for our Ruby on Rails application. As the goal of this tutorial is to show you how to best leverage various GCP services, let’s rely on Google Cloud Build (GCB) to assemble our container.

Prior to launching the build command we must grant Cloud Build (or more precisely the service account that impersonates Cloud Build) with the cloudkms.cryptoKeyDecrypter role on the three pieces of information that we encrypted earlier (see Part 3). With this role Cloud Build is able to decrypt those secrets when needed in the build process (more on this in the cloudbuild.yaml file below).

To find the name of the Cloud Build service account that is automatically created by GCP, visit the Google Cloud Platform Console IAM page and look for an account with role “Cloud Build Service Account” matching the following pattern: xxx...xxx@cloudbuild.gserviceaccount.com .

Running the Build operation

Rather than mobilizing the processing power of your local machine to build the application container, let’s delegate that task to Google Cloud Build. As of the writing of this article, the first 120 builds-minutes *per day* are free of charge, you only pay for the space used by container images in Google Cloud Storage which in turn provides you with 5GB of free space. Our container image being less than 100 MB in size, it means you won’t be paying a dime unless you insist on keeping the last 50 versions of your builds. And if it ever comes to that point you are still covered with your $300 free credit.

Let’s spend some time reviewing the configuration files that Cloud Build will be using. Both of them can be found at the root of the source code repository.

cloudbuild.yaml: this file describe the steps Cloud Build has to go through to build your container. The file itself is made of four steps. Actually it’s five but the first one is implicit:

  1. Create a compressed tarball of the source directory (the current directory you are working in), transfer it over to the GCS bucket and untar the archive in the Cloud Build workspace.
  2. Ask Cloud KMS to decrypt the master.key.enc file so that it is available for the rest of the build process (and also in the future container that we will publish)
  3. Do the same for the service account credentials
  4. Build the container as instructed in Dockerfile and, before that make sure to decrypt the production database password and pass it as an environment variable (DB_PWD)
  5. Push the new image to Container Registry for deployment in production by Cloud Run

Dockerfile: this file is invoked by the ‘Build image’ step in Cloud Build. Read the comments below to find out what each statement does.

And finally, find below the entrypoint.sh script that is going to run each time a new container instance is started by Cloud Run. It calls for a couple of remarks:

  1. The db:create rake task will actually create the database on the very first launch of a Cloud Run instance and has no effect on subsequent runs
  2. Running db:migrate in the entrypoint script is a convenient trick. However it may occasionally generate error messages in the logs resulting from concurrent Cloud Run instances starting at once. It is quite harmless though.
  3. $PORT is provided by Cloud Run at runtime along with a number of other environment variables.

It is now time to build the container:

$ gcloud builds submit --config cloudbuild.yaml

Logs of the build steps should unroll on your screen. After a couple of minutes you should see a success message along with the name of the container image just created.

Note: Build logs are also available in ~/.config/gcloud/logs and from the Google Cloud Web Console under Menu > Cloud Build in case you need to further investigate.

Cloud Build Web Console showing the latest build

If your build is successful Cloud Build will also push the latest container image in Container Registry for you under the photo-album folder:

Container Registry Web Console showing the latest container image built

Checking for vulnerabilities

Using a serverless service like Cloud Run definitely makes your life much easier when it comes to deploying in production. You can basically forget about all the intricacies of managing your own servers or clusters. There is one thing though that you must not forget about : it’s to make sure that the containers you build and deploy are secure and immune to attacks.

Luckily from the Settings menu of Container Registry you can activate the Vulnerability scanning API (see screenshot below). It’s still in beta as I’m writing this article but I urge you to activate this feature right now as it will help you uncover any lurking vulnerabilities in your image before actually deploying in production. A *VERY* useful service.

Enabling automatic container images vulnerability scanning in Container Registry

Deploying your application

If your build went well and you find no critical vulnerabilities on your path, you can ask Cloud Run to deploy the image you just built:

The first argument ‘photo-album’ is the name we give to our Cloud Run service. It is automatically instantiated at the first deployment.

  • The second argument is the path to the image with just built and registered with Container Registry.
  • The third argument tells Cloud Run which Cloud SQL to use for this service. If you make other deployments this third argument is not needed as Cloud Run persist it from one revision of the service to the next.
  • The last argument tells Cloud Build to ignore the authentication step. This works because you are granted the role project.owner on the project you have created.

The deployment will take a minute or so and a final message tells you about the public URL of your application. From that moment you are on-air!

Cloud Run revisions screen

Monitoring your application

Keeping an eye on your application once it’s deployed in production is not an option. The very first thing to do is to make sure that Cloud Run captures Rails logs. Cloud Run monitors a number of I/O sources for log messages one of them being the standard output. It turns out that starting with Rails 5, redirecting Rails production log to STDOUT is just a matter of setting the RAILS_LOG_TO_STDOUT environment variable. That’s why you’ll find the following statement in the Dockerfile:

# Redirect Rails log to STDOUT for Cloud Run to capture
ENV RAILS_LOG_TO_STDOUT=true

Cloud Run logs are available under the LOGS tab from the Cloud Run Web Console (see screenshot above).

In addition to gathering system and application log messages, Cloud Run also collect a number of metrics like Request Count, Request Latency as well as Container CPU and memory allocation. Metrics are available from the tab of the same name (see screenshot above).

Collecting Rails logs with Cloud Run is a first step. A more advanced alternative is to use Google Stackdriver not only to collect log messages but also activate application monitoring/alerting, stack tracing and source code level debugging whenever error pop up. But we leave that subject for another article. 😄

Conclusion

Congratulations ! You made it to the end of this tutorial. Sure, that was a lot of information to digest but you now have in your a solid foundation to securely deploy Rails application and make them scale at will. Cloud Run is still in beta as I write this article but it’s already a very stable and scalable product. Expect more feature announcements in the coming weeks and months.

Of course this is by no means a comprehensive article. There are many other GCP services you’d probably like to leverage in a Rails application such as :

  • Using Cloud Task to trigger asynchronous background processing tasks (e.g. generate thumbnails of your photos in the background)
  • Spawning periodic tasks with Cloud Scheduler
  • Redirect Rails log message to Stackdriver for more advanced monitoring, alerting and debugging features
  • Conducting a performance study to find the best Cloud Run instance memory limits to concurrency level ratio for your application.

Each topic could be (will be ? 😉) the subject of an article in itself. So feel free to elaborate and enjoy the power of Rails on Google Cloud Run.

As always, comments are welcome.

--

--