Rails6 on Google Cloud Run
Sumiki Ohsawa
Posted on July 14, 2020
What makes me look into it?
- It works if it is containerized, no version requirements
- It is serverless, pay as you use, it is good for experimental projects.
- Gcloud offers autoscaling (fully managed).
- Gcloud console. I like how google implements web cloud console.
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
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
}
Posted on July 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.