In this codelab, you will learn how to deploy a new Ruby on Rails application using Google Cloud SQL for PostgreSQL to Google App Engine Flexible environment.

Google Cloud SQL for PostgreSQL is a fully-managed database service that makes it easy to set up, maintain, manage, and administer your PostgreSQL relational databases on Google Cloud Platform.

Google App Engine Flexible environment applications are easy to create, easy to maintain, and easy to scale as your traffic and data storage changes. With App Engine, there are no servers to maintain. You simply upload your application and it's ready to go.

App Engine applications automatically scale based on incoming traffic. load balancing, microservices, authorization, SQL and NoSQL databases, traffic splitting, logging, search, versioning, roll out and roll backs, and security scanning are all supported natively and are highly customizable.

What you'll learn

What you'll need

Survey

How will you use this tutorial?

Read it through only Read it and complete the exercises

How would you rate your experience with Ruby?

Novice Intermediate Proficient

How would you rate your experience with using Google Cloud Platform services?

Novice Intermediate Proficient

Self-paced environment setup

If you don't already have a Google Account (Gmail or Google Apps), you must create one. Sign-in to Google Cloud Platform console (console.cloud.google.com) and create a new project:

Remember the project ID, a unique name across all Google Cloud projects (the name above has already been taken and will not work for you, sorry!). It will be referred to later in this codelab as PROJECT_ID.

Next, you'll need to enable billing in the Developers Console in order to use Google Cloud resources.

Running through this codelab shouldn't cost you more than a few dollars, but it could be more if you decide to use more resources or if you leave them running (see "cleanup" section at the end of this document). Google Kubernetes Engine pricing is documented here.

New users of Google Cloud Platform are eligible for a $300 free trial.

Start Cloud Shell

While Google Cloud can be operated remotely from your laptop, in this codelab you will be using Google Cloud Shell, a command line environment running in the Cloud. This Debian-based virtual machine is loaded with all the development tools you'll need (gcloud, ruby, gem and more), it offers a persistent 5GB home directory, and runs on the Google Cloud, greatly enhancing network performance and authentication. This means that all you will need for this codelab is a browser (yes, it works on a Chromebook).

Activate Google Cloud Shell

From the GCP Console click the Cloud Shell icon on the top right toolbar:

Then click "Start Cloud Shell":

It should only take a few moments to provision and connect to the environment:

This virtual machine is loaded with all the development tools you'll need. It offers a persistent 5GB home directory, and runs on the Google Cloud, greatly enhancing network performance and authentication. Much, if not all, of your work in this lab can be done with simply a browser or your Google Chromebook.

Once connected to the cloud shell, you should see that you are already authenticated and that the project is already set to your PROJECT_ID:

gcloud auth list

Command output

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Command output

[core]
project = <PROJECT_ID>

If it is not, you can set it with this command:

gcloud config set project <PROJECT_ID>

Command output

Updated property [core/project].

Before you can begin using the Cloud SQL you must enable the Admin API. Using the Cloud Shell you can enable the API by using the following command:

gcloud service-management enable sqladmin.googleapis.com

In the following steps you will create a PostgreSQL instance that you will use in the following codelab.

Create a PostgreSQL instance named postgres-instance:

gcloud beta sql instances create postgres-instance \
    --database-version POSTGRES_9_6 \
    --tier db-g1-small

Creating a new PostgreSQL instance will take a few moments.

Next, set the password for the postgres user and replace [PASSWORD] with a password of your choice:

gcloud beta sql users set-password postgres no-host \
    --instance postgres-instance \
    --password [PASSWORD]

Your Cloud SQL for PostgreSQL instance is now ready for the following steps.

When deployed, your application uses the Cloud SQL Proxy that is built into the App Engine environment to communicate with your Cloud SQL instance. However, to test your application using the Cloud Shell, you must install a copy of the Cloud SQL Proxy in the development environment.

Next, you will download and setup the Cloud SQL Proxy using the Cloud Shell.

Download the Cloud SQL Proxy:

wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64

Rename the proxy to use the standard filename:

mv cloud_sql_proxy.linux.amd64 cloud_sql_proxy

Make the proxy executable:

chmod +x cloud_sql_proxy

Create a directory where the proxy sockets will live:

sudo mkdir /cloudsql
sudo chmod 0777 /cloudsql

The proxy is now ready to be used. Next, you will obtain the connectionName for the Cloud SQL for PostgreSQL instance and use it to connect the cloud_sql_proxy to instance you created in the previous step.

To retrieve the Instance Connection Name, run:

gcloud beta sql instances describe postgres-instance | grep connectionName

Copy the connectionName and use to replace the value of [YOUR_INSTANCE_CONNECTION_NAME]:

./cloud_sql_proxy -dir=/cloudsql \
                  -instances="[YOUR_INSTANCE_CONNECTION_NAME]"

You should see the following output:

2017/04/19 12:42:21 Listening on /cloudsql/postgres-rails:us-central1:postgres-instance/.s.PGSQL.5432 for postgres-rails:us-central1:postgres-instance
2017/04/19 12:42:21 Ready for new connections

You will keep this open as you continue through this codelab.

While the Cloud SQL Proxy is running. You will need to run the remaining steps in a new Cloud Shell tab.

Open another Cloud Shell tab using the "+" button:

Next, you will install Ruby on Rails.

Install the rails gem by using:

gem install rails

Now, you can verify the gem installation by using:

rails --version

You should see something similar to the following:

Rails 5.x.x

Now that you have Rails installed, you can generate the scaffolding of a new Rails app by using:

rails new app_name

Move into the directory created by Rails for the application:

cd app_name

You can view the generated files for a new Rails applications by using:

ls

You should see something similar to:

Now that we have a Rails app, let's test it using the Web Preview functionality provided by the Cloud Shell environment. By default the Web Preview uses port 8080.

Before running the Rails server, run the following command to install necessary gems:

bundle install

Start the Rails app server listening on port 8080:

bundle exec rails server --port 8080

Once the application starts, click on the Web Preview icon in the Cloud Shell toolbar and choose Preview on port 8080.

A tab in your browser opens and connects to the server you just started. You should see the following image!

You can now stop the Rails server by using (Ctrl + c) in the Cloud Shell.

You must first add the pg gem to the file Gemfile to begin using Google Cloud SQL for PostgreSQL.

Open the file Gemfile and add the line gem pg. You should something similar to the following.

source 'https://rubygems.org'

git_source(:github) do |repo_name|
  repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
  "https://github.com/#{repo_name}.git"
end

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails'

# Added pg for codelab
gem 'pg'

Next, update the installed dependencies:

bundle install

Now, you can configure your Rails app to communicate with Cloud SQL for PostgreSQL.

Open the file config/database.yml, and you should see the following boilerplate database settings for SQLite:

# SQLite version 3.x
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: sqlite3
  pool: 5
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  database: db/production.sqlite3

Before you can modify the database.yml file, you need the Cloud SQL for PostgreSQL Instance Connection Name for the App Engine production environment.

To retrieve the Instance Connection Name, run:

gcloud beta sql instances describe postgres-instance | grep connectionName

Next, copy the value next to connectionName to your clipboard, ignore /.s.PGSQL.5432. Next, modify the database.yml production database configuration to the following, replacing [PLACEHOLDERS] with associated values.

production:
  adapter: postgresql
  pool: 5
  timeout: 5000
  username: postgres
  password: [PASSWORD]
  database: postgres-database
  host: /cloudsql/[YOUR_INSTANCE_CONNECTION_NAME]

The Rails app is now set up to use Cloud SQL for PostgreSQL in a production environment. These instructions can be used to set up Cloud SQL for test and development environments.

The new model contains a list of cat names and ages. You can generate a new Rails ActiveRecord model by using the following command:

bundle exec rails generate model Cat name:string age:decimal

This generates a model named Cat, a database table named cats, and a migration file with a similar name to db/migrate/20170302062657_create_cats.rb.

You can now update the production Cloud SQL for PostgreSQL instance database postgres_instance with the following command:

RAILS_ENV=production bundle exec rails db:create
RAILS_ENV=production bundle exec rails db:migrate

You should see a similar output to the following for a successful migration.

== 20170302062657 CreateCats: migrating ============================
-- create_table(:cats)
   -> 0.0585s
== 20170302062657 CreateCats: migrated (0.0586s) ===================

Using the Rails console, you can try the new Cat model by adding a few cats.

Start the Rails console by using the following command:

RAILS_ENV=production bundle exec rails console

With the Rails console open, you can add two cat friends by using the following Ruby code:

Cat.create name: "Mr. Whiskers", age: 4
Cat.create name: "Ms. Paws", age: 2

Each line creates a new entry in the database containing the provided cats.

To exit the Rails console, use:

exit

Now add a page to display a list of cats to the generated Rails application. You can generate the scaffolding for a new page by using rails generate. The following command creates a new Rails controller named CatFriendsController with an index action:

bundle exec rails generate controller CatFriends index

This command generates the following new directories and files by default for the new CatFriendsController controller and index action:

create  app/controllers/cat_friends_controller.rb
 route  get 'cat_friends/index'
invoke  erb
create    app/views/cat_friends
create    app/views/cat_friends/index.html.erb
invoke  test_unit
create    test/controllers/cat_friends_controller_test.rb
invoke  helper
create    app/helpers/cat_friends_helper.rb
invoke    test_unit
invoke  assets
invoke    coffee
create      app/assets/javascripts/cat_friends.coffee
invoke    scss
create      app/assets/stylesheets/cat_friends.scss

Next, set the index controller action as the root action for Rails, and whenever a user visits the Rails app, they can see the list of cats.

Open the file config/routes.rb to see the following generated content:

Rails.application.routes.draw do
  get 'cat_friends/index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

end

Modify this file by adding root cat_friends#index:

Rails.application.routes.draw do
  get 'cat_friends/index'
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  root 'cat_friends#index'
end

Save the file and close it.

Next, you will modify the Rails app to display entries in the database.

Open the file app/controllers/cat_friends_controller.rb and set an instance variable @cats to contains all cat entries. Your file should be similar to the following:

class CatFriendsController < ApplicationController
  def index
    @cats = Cat.all
  end
end

Next, open the file app/views/cat_friends/index.html.erb, and add Ruby code to display each cat entry in @cats. Your file should be similar to the following:

<h1>A list of my Cats</h1>

<% @cats.each do |cat| %>
<%=cat.name%> is <%=cat.age%> years old!<br />
<% end %>

Save the file and close it.

Before we can test the Rails app, you need to define a secret key for the production environment in the Cloud Shell. A secret key is used to protect user session data.

You can generate a secret key by using:

bundle exec rails secret

Using the generated secret key, set the environment variable SECRET_KEY_BASE with the secret key as its value by using:

export SECRET_KEY_BASE=[SECRET_KEY]

Test the Rails app with the Web Preview by using the following command:

RAILS_ENV=production bundle exec rails assets:precompile
RAILS_ENV=production bundle exec rails server --port 8080

Once the application starts, click on the Web Preview icon in the Cloud Shell toolbar and choose Preview on port 8080.

A tab in your browser opens and connects to the server you just started. You should see the following image!

You can now stop the Rails server by using (Ctrl + c) in the Cloud Shell.

Now that you have a working Cloud SQL for PostgreSQL with Rails app. Let's deploy it to App Engine flexible environment!

App Engine Flexible environment uses an app.yaml file to describe an application's deployment configuration. If this file is not present, the gcloud tool will try to guess the deployment configuration. However, it is a good idea to provide this file because Rails requires a secret key in production and App Engine requires the connectionName for the Cloud SQL instance.

Recall, you can generate a secret key by using:

bundle exec rails secret

Copy the secret key that's generated to your clipboard because you will use it in the next step.

Create a new file called app.yaml using vim, nano, or emacs, and add the following in the file:

entrypoint: bundle exec rackup --port $PORT
env: flex
runtime: ruby

env_variables:
  SECRET_KEY_BASE: [SECRET KEY]

beta_settings:
  cloud_sql_instances: [YOUR_INSTANCE_CONNECTION_NAME]

Replace [SECRET KEY] with the generated secret key and [YOUR_INSTANCE_CONNECTION_NAME] with the connectionName of the Cloud SQL for PostgreSQL instance.

When the app is deployed, the environment variable SECRET_KEY_BASE in production will be set with the secret key and App Engine will set up the Cloud SQL Proxy to communicate with the Cloud SQL for PostgreSQL instance.

First, you need to create an App Engine instance by using:

gcloud app create

After this command completes, you can deploy your app on App Engine by using:

gcloud app deploy

Check out your Rails App!

After the application is deployed, you can visit it by opening the URL

https://[PROJECT_ID].appspot.com in your web browser.

You should see your List of Cats! Here's an example of what you should see:

In this codelab you learned how to use Cloud SQL for PostgreSQL using Ruby on Rails and then deploy it to App Engine flexible environment.

Clean up

To avoid incurring charges to your Google Cloud Platform account for the resources used in this quickstart:

Learn More

License

This work is licensed under a Creative Commons Attribution 2.0 Generic License.