Why Google Cloud Run?
-
Write code your way using your favorite languages (Go, Python, Java, Ruby, Node.js, and more)
-
Abstract away all infrastructure management for a simple developer experience
-
Built upon an open standard Knative, enabling the portability of your applications
In terms of “usual” Ruby On Rails application with background jobs for example (let’s say Sidekiq), you’ll need to make some additional code changes, cause you can’t run Sidekiq workers on Cloud Run
Useful links
Google Cloud Run website:
Some additional links:
https://cloud.google.com/build
https://cloud.google.com/tasks
https://cloud.google.com/scheduler
Great CloudTasker gem for background jobs (you can’t run Sidekiq with Google Cloud Run):
https://github.com/keypup-io/cloudtasker
Good article about Rails Active Job + Google Cloud Tasks:
https://www.keypup.io/blog/google-cloud-tasks-with-rails-active-job
Setup Google Cloud SQL
What is Google Cloud SQL?
Fully managed relational database service for MySQL, PostgreSQL, and SQL Server.
-
Reduce maintenance cost with fully managed relational databases in the cloud
-
Ensure business continuity with reliable and secure services backed by 24/7 SRE team
-
Automate database provisioning, storage capacity management, and other time-consuming tasks
-
Database observability made easy for developers with Cloud SQL Insights
-
Easy integration with existing apps and Google Cloud services like GKE and BigQuery
Go to the Cloud SQL section in your GCP console.
Create database - mysql/postgresql:
~ ❯❯❯ gcloud beta sql instances create mydbinstance \
--database-version POSTGRES_9_6 \
--cpu=1 --memory=3840MiB --region=northamerica-northeast1-a
Create user:
~ ❯❯❯ gcloud sql users set-password postgres \
--instance=mydbinstance \
--password=my-password
Google Cloud Build
What is Google Cloud Build?
-
Build software quickly across all programming languages, including Java, Go, Node.js, and more
-
Get complete control over defining custom workflows for building, testing, and deploying
-
Deploy across multiple environments such as VMs, serverless, Kubernetes, or Firebase
-
Perform deep security scans as part of your CI/CD pipeline
-
Package source into containers or non-container artifacts such as Maven, Gradle, Go, or Bazel
Project page:
https://cloud.google.com/build
Set PROJECT_ID
Let’s setup variable with your GCP project ID.
We’ll use it later in our configuration setup.
~ ❯❯❯ PROJECT_ID=project_id
~ ❯❯❯ gcloud auth login your_account_name
~ ❯❯❯ gcloud config set project $PROJECT_ID
Activating API’s
~ ❯❯❯ gcloud services enable run.googleapis.com
~ ❯❯❯ gcloud services enable cloudkms.googleapis.com
~ ❯❯❯ gcloud services enable sqladmin.googleapis.com
~ ❯❯❯ gcloud services enable run.googleapis.com
Google Cloud Run Region
Let’s run configuration config change and set region.
gcloud config set run/region northamerica-northeast1-a
Service account
As a next step we’ll need to create a service account.
~ ❯❯❯ gcloud iam service-accounts create service-account-name --display-name "Cloud Run Service Account"
# Check your accounts
~ ❯❯❯ gcloud iam service-accounts list
Using service account and set access
Let’s set access rights and create key file.
~ ❯❯❯ SERVICE_ACCOUNT=service-account-name@$PROJECT_ID.iam.gserviceaccount.com
# Set cloudsql access rights
~ ❯❯❯ gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:$SERVICE_ACCOUNT --role roles/cloudsql.client
# Create key file
~ ❯❯❯ gcloud iam service-accounts keys create ./config/my_app.key --iam-account service-account-name@$PROJECT_ID.iam.gserviceaccount.com
Working with secrets
~ ❯❯❯ gcloud kms keyrings create myapp --location=northamerica-northeast1-a
# Service account credentials encrypt
~ ❯❯❯ gcloud kms keys create myapp_key --location northamerica-northeast1-a --keyring myapp --purpose encryption
~ ❯❯❯ gcloud kms encrypt - location northamerica-northeast1-a --keyring myapp \
--key myapp_key --plaintext-file ./config/myapp_key.key \
--ciphertext-file ./config/myapp_key.key.enc
# Rails master key
~ ❯❯❯ gcloud kms keys create rails_master_key --location northamerica-northeast1-a --keyring myapp --purpose encryption
~ ❯❯❯ gcloud kms encrypt --location northamerica-northeast1-a --keyring myapp \
--key rails_master_key --plaintext-file ./config/master.key \
--ciphertext-file ./config/master.key.enc
Cloud Run deployment config
Before doing what make sure that you have secrets for your DB configuration (DB_PWD variable for example, but it’s optional).
Simple steps:
-
Decrypting master.key file
-
Decrypting service account credentials
-
Building latest image with secrets
timeout: 1200s
steps:
# Decrypt Rails Master key file
- name: gcr.io/cloud-builders/gcloud
args: ["kms", "decrypt", "--ciphertext-file=./config/master.key.enc",
"--plaintext-file=./config/master.key",
"--location=northamerica-northeast1-a","--keyring=myapp",
"--key=rails_master_key"]
# Decrypt app service account credentials
- name: gcr.io/cloud-builders/gcloud
args: ["kms", "decrypt", "--ciphertext-file=./config/myapp_key.key.enc",
"--plaintext-file=./config/myapp_key.key",
"--location=northamerica-northeast1-a","--keyring=myapp",
"--key=myapp_key"]
# Build image with tag 'latest'
- name: 'gcr.io/cloud-builders/docker'
args: ['build', '--tag', 'gcr.io/PROJECT_URL',
'--build-arg', 'DB_PWD', '.']
secretEnv: ['DB_PWD']
# Push new image to Google Container Registry
- name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/PROJECT_URL']
secrets:
- kmsKeyName: projects/YOUR_PROJECT_ID/locations/northamerica-northeast1-a/keyRings/myapp/cryptoKeys/db_pwd_key
secretEnv:
DB_PWD: "XXX"
Let’s take a look to our Dockerfile (depends on your app):
FROM ruby:2.6.2
RUN apt-get update && apt-get install -y build-essential git
RUN apt-get install -y libpq-dev
RUN apt-get install -y nodejs
RUN mkdir -p /app
WORKDIR /app
ENV LANG C.UTF-8
COPY Gemfile Gemfile.lock ./
RUN gem install bundler && bundle install --jobs 20 --retry 5
COPY . $APP_ROOT
ARG BUILD_SHA=unknown
ARG DB_PWD
ENV DATABASE_PASSWORD=${DB_PWD}
ENV BUNDLE_FROZEN=true
ENV BUILD_SHA ${BUILD_SHA}
ENV RAILS_LOG_TO_STDOUT=true
ENV RAILS_ENV production
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]
Entrypoint.sh file example.
#!/bin/bash
cd /app
RAILS_ENV=production bundle exec rake db:create
RAILS_ENV=production bundle exec rake db:migrate
RAILS_ENV=production bundle exec rake db:seed
bundle exec rails s -e production
Submit cloud build run
Our last step - just submit our yaml file and check dashboard for the progress!
~ ❯❯❯ gcloud builds submit --config cloudbuild.yaml
That’s it! Run/deploy/test and stay tuned.