I am taking some qwiklab courses for my better understanding of google cloud recently. My badges are here. CloudRun is interesting and I look into how I can deploy rails6 app on it.

What makes me look into it?

  • CloudRun works as long as it containerized, no language and version requirements
  • It is serverless, pay as you use. Cheap.
  • Gcloud offers autoscaling (fully managed).

Source Code

The source code I tried in this article is here.
https://github.com/sumiki/cloud_run_rails

Install Rails

rbenv install 2.7.1
gem install rails 
rails new cloud_run_rails -o
I tried rails without a database this time just to see how cloud run works.

Update rails to Edge (There is no requirement to ruby versions, so try edge)

# Gemfile
gem 'rails', github: 'rails/rails'

Then

bundle install

Add JS

There are no life without javascript so add some code and locally run precompile

RAILS_ENV=production bundle exec assets:precompile 

Dockerlize

# Gemfile
FROM ruby:2.7
WORKDIR /app
COPY Gemfile Gemfile.lock ./
ENV RAILS_ENV production
RUN bundle install
COPY . .
EXPOSE 3000
ENV RAILS_SERVE_STATIC_FILES true
CMD ["bin/rails", "server", "-b", "0.0.0.0"]

Build docker container

docker build -t cloud_run_rails:0.0.1 .

Run it locally

docker run -d -it -p  3000:3000  cloud_run_rails:0.0.10

Deploy to Cloud Run

Push container to cloud repository

GOOGLE_CLOUD_PROJECT=<your project name>

docker tag cloud_run_rails:0.0.1 us.gcr.io/${GOOGLE_CLOUD_PROJECT}/cloud_run_rails:0.0.1

docker push us.gcr.io/${GOOGLE_CLOUD_PROJECT}/cloud_run_rails:0.0.1
gcloud run deploy --image=us.gcr.io/${GOOGLE_CLOUD_PROJECT}/cloud_run_rails:0.0.1 --platform managed --concurrency 1

It is running Running Rails on Cloud Run

A problem I saw

There is one thing I got stuck and could not figure out for a day. I was able to run rails app development mode on cloud run but not production mode.

In the cloud run document there is a command to dockerize the app.

gcloud builds submit --tag us.gcr.io/${GOOGLE_CLOUD_PROJECT}/cloud_run_rails:0.0.1

https://cloud.google.com/sdk/gcloud/reference/builds/submit

This makes rails in production mode not work on cloud run. This command is supposed to build a Docker container and push it to the repository. But it looks like it happened remotely on gcloud. It transfers the source code using git and that’s end up miscopying config/master.key and compiled assets. We can build container locally and use .dockerignore to prevent copying files not needed on the container.

Terraform

We are also able to manage the cloud resources using terraform.

terraform apply -var-file=prod.tfvars
# tf/main.tf
provider "google" {
 version = "3.5.0"

 credentials = file(var.credentials_path)

 project = var.project_name
}

resource "google_cloud_run_service" "default" {
 name     = var.cloud_run_name
 location = "us-west1"

 template {
   spec {
     containers {
       image = var.docker_image_path
     }
   }
 }

 traffic {
   percent         = 100
   latest_revision = true
 }
}

data "google_iam_policy" "noauth" {
 binding {
   role = "roles/run.invoker"
   members = [
     "allUsers",
   ]
 }
}

resource "google_cloud_run_service_iam_policy" "noauth" {
 location    = google_cloud_run_service.default.location
 project     = google_cloud_run_service.default.project
 service     = google_cloud_run_service.default.name

 policy_data = data.google_iam_policy.noauth.policy_data
}