Kubernetes Development Blog
  • Docs
  • GitHub
  • Blog
  • Install

›Recent Posts

Recent Posts

  • DevOps and the Cloud: Tools and Technologies for Forward Looking DevOps Teams
  • The Missing Kubernetes Platform for Developers
  • How to Give Developers Access to Kubernetes During Development
  • How to deal with computing resource cost for Kubernetes-based development
  • Why Cloud Development Could (Finally) Become the New Standard

Deploy Ruby on Rails to Kubernetes

October 21, 2019

Lukas Gentele

Lukas Gentele

Optimized Development and Deployment Workflow For Ruby on Rails on Kubernetes

Rails is a powerful framework that comes with batteries loaded. One thing that is not available out of the box is a simple way of deploying Rails projects to Kubernetes and a time-saving method for iteratively developing Rails projects on top of Kubernetes.

In this tutorial, we are taking DevOps to the next level by showing how developers can build Rails applications using Kubernetes. This tutorial is great for Kubernetes beginners but also for advanced users that want to streamline their development and deployment workflow for Rails on Kubernetes.

This tutorial works with any Kubernetes cluster (minikube, Docker Kubernetes, GKE, EKS, AKS, loft vCluster etc.).

1. Create Rails Project

Obviously, you can skip this step if you already have a Rails project that you want to use for the purpose of this tutorial.

Before creating a Rails project, let's define a variable with the directory that we want our Rails project to be located in:

PROJECT_DIR=/c/Users/[username]/my-rails-project  # for git-bash on windows
PROJECT_DIR=/home/[username]/my-rails-project     # for unix-based systems (mac, linux)

If you are using Docker Toolbox , your $PROJECT_DIR needs to be inside your user's home directory, e.g. /c/Users/[username].

If you are using the newer Docker Desktop on Windows, make sure the drive that your project should be on is marked as Shared Drive in the Docker settings.

Now, let's also create a variable for the name of our Rails project:

PROJECT_NAME=app

If you don't have a Rails app at hand, this code snippet is a great way to leverage Docker for creating a Rails project super quickly:

mkdir $PROJECT_DIR
docker run --rm -v /$PROJECT_DIR:/app -w //app ruby:2.6-alpine sh -c "apk add build-base nodejs yarn tzdata sqlite-dev postgresql-client postgresql-dev && gem install pg rails && rails new $PROJECT_NAME --database=postgresql"
cd $PROJECT_DIR/$PROJECT_NAME

This command may take quite some time but if you are familiar with Ruby on Rails, you probably already know that.

As you can see in the code snippet, we are using the --database=postgresql because we want to add a PostgreSQL database later on (of course you can skip this if that's not what you need).

2. Containerize Project

So, let's containerize our Rails project. To do this in a quick and easy way, we are using DevSpace, an open-source dev tool for Kubernetes. DevSpace is a client-only CLI tool for containerizing projects and it is the fastest tool for interactively deploying applications to Kubernetes.

There is no Ruby gem for DevSpace but you can easily install DevSpace via npm:

npm install -g devspace

For more install options, take a look at the GitHub repo.

After installing DevSpace, containerizing a project is pretty straight forward. Just run this command:

devspace init

When DevSpace asks you which port the application is listening on, type in 3000 and hit Enter. The remaining questions should be easy to answer. You can always hit Enter to just select the default option if you are unsure.

After the init process is done, you're ready to deploy the project to Kubernetes. However, if you need a database, it is smart to add it before deploying the project.

Bonus: Add Postgres Database

Open the file devspace.yaml (which was created by devspace init) and change the deployments section from:

deployments:
- name: app
  helm:
    componentChart: true
    values:
      containers:
      - image: dscr.io/${DEVSPACE_USERNAME}/app
      service:
        ports:
        - port: 3000

to:

deployments:
- name: database
  helm:
    chart:
      name: stable/postgresql
      version: "6.5.9"
    values:
      postgresqlDatabase: "db_app"
      postgresqlUsername: "db_user"
      postgresqlPassword: ${DB_PASSWORD}
- name: app
  helm:
    componentChart: true
    values:
      containers:
      - image: dscr.io/${DEVSPACE_USERNAME}/app
        env:
        - name: DATABASE_URL
          value: "postgres://db_user:${DB_PASSWORD}@database-postgresql/db_app"
      service:
        ports:
        - port: 3000

As you can see, we can use the values section in the configuration of this postgresql deployment to set the database name, user and password. Keep in mind that unlike most other config options these settings shown above are only used the very first time you deploy the database. That means that after deploying the database for the first time, you will need to connect to the database and change username/password etc. manually if you want to change this later on.

To view a list of all available config options (i.e. values) for this mysql deployment, take a look at the documentation of this Helm chart on GitHub.

Done! That's it, now you can deploy this Ruby project and will immediately have a PostgreSQL database ready to be used by the application.

3. Choose Kubernetes Cluster

To run your Ruby on Rails app on Kubernetes, you need access to a Kubernetes cluster. If you are just playing around and experimenting, local Kubernetes solutions such as minikube, Kubernetes in Docker (kind), or MicroK8s are probably a good starting point. If you prefer to have a cloud-based Kubernetes environment, you can use any cloud provider. Many of them are also providing free credits, e.g. Google Cloud or Azure. For a more advanced solution that is suited for engineering teams, you can connect your Kubernetes cluster to loft, which then allows all engineers to create isolated virtual clusters on a shared physical cluster. This enables them to create virtual clusters whenever they need them in a streamlined way via the loft UI, the vCluster CRD or the loft CLI that can also be integrated into DevSpace with the loft-devspace-plugin.

Since DevSpace works with any Kubernetes cluster, the next step is always the same, no matter which cluster you want to use:

Just tell DevSpace which namespace to use (will be created during deployment if not existing):

devspace use namespace [my-namespace]

4. Develop Project

Before we deploy this Rails project, we need to establish a workflow for developing the project as efficiently as possible. DevSpace provides a command for this workflow:

devspace dev

The first time you run this command, DevSpace will ask you to define a database password that is used for the variable DB_PASSWORD.

Running this for the first time may take a while but will be much quicker the second time.

This command essentially builds the Docker image from the Dockerfile, tags it and pushes it to a registry. Then, DevSpace deploys the project according to the deployments section of the devspace.yaml and starts the development services (port-forwarding for localhost access, log streaming and file sync for hot reloading).

If everything is up and running as expected, you should be able to see the Rails logs in the terminal and the browser will open showing the famous Rails welcome page on localhost:3000.

Ruby on Rails Welcome Page - Every Rails developer's favorite page to see.

In addition to deploying our Rails application to Kubernetes, the devspace dev command also starts a powerful development UI which runs on localhost and is available as long as the devspace dev command is running.

You should see a log statement similar to this one in the output of devspace dev:

#########################################################
[info]   DevSpace UI available at: http://localhost:8090
#########################################################

So go ahead and check out the DevSpace UI in your browser! You can use it to see the container and pod status of your deployments as well as to stream logs and open interactive terminal sessions for every container. It should look like in this screencast:

DevSpace: Kubernetes Development UI - Screencast
Get new blog articles via email!
Subscriptions

Generate Index Route

Now that the project is running inside the Kubernetes cluster, we can start developing the actual business logic. Of course, you can also run the usual rails commands locally, but in this tutorial, I will show you how to run these commands directly inside the running container.

Make sure devspace dev is still running before continuing with this part of the tutorial. Just leave it running or start it again and open a second terminal to run the following commands.

To generate a controller for a "Hello World" index page, run the following command:

devspace enter -- rails generate controller Welcome index

As you can see we are executing a regular rails command. By adding the prefix devspace enter --, we tell DevSpace to run this rails command inside a container within Kubernetes instead of executing it on the local machine. You could also run any other rails, npm or bundle command within the container by just adding devspace enter -- before the command.

Then, as usual change the config/routes.rb on your local filesystem from:

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end

to:

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

DevSpace makes sure that any file changes on the remote system will be reflected on the local filesystem and vice versa. That is the fastest way to iteratively build Kubernetes-based applications.

You can see how quick this is if you just edit a single file. Go ahead and try it:

  1. Replace "Welcome#index" with "Hello World" text inside the file app/views/welcome/index.html.erb
  2. Reload the browser to see the changes and also take a look at the logs of the devspace dev command which are streamed in real-time from the container inside the Kubernetes cluster.

Extra: Add Posts

We wouldn't need a database if we didn't have any data to persist. So, for the purpose of this tutorial, let's generate a Rails scaffold for blog posts:

devspace enter -- rails generate scaffold Post title:string body:text

After creating the scaffold, we need to invoke rake for a database migration:

devspace enter -- rake db:migrate

That's it! Everything is already live:

  1. Go to this URL: http://localhost:3000/posts
  2. Add posts and see how they are persisted to the database.
  3. Observe the logs streamed via devspace dev while you add new posts.

5. Deploy Project

If you reached this part of the tutorial, you got the hang of the development flow. Now, it's time to deploy the application for good. In most cases, you may want to create another space using devspace create space myapp-prod or run devspace use namespace [prod-namespace] to separate dev and production. You can always switch back to the development workspace using the devspace use space/namespace command.

Once you're in the right kube-context and namespace, you can deploy your project with the following command:

devspace deploy

Before you can access the deployed Rails project, you need to wait until the database migrations run through and the app starts listening. You can check the status of this process by streaming the logs of the app container using this command:

devspace logs -f

After you see the following log line:

* Listening on tcp://0.0.0.0:3000

you can access your deployed Rails app with this command:

devspace open

DevSpace can either start a private port-forwarding session for you (for localhost access similar to devspace dev) or it can create a Kubernetes ingress for you to make your project publicly available on a domain.

What's next?

There is so much more to show in terms of better productivity for Kubernetes and Rails. If you are interested in the next article, subscribe and you'll get an email as soon as my next article is out.

If this is helpful to you or you have any questions or ideas what might be interesting to blog about next, reach out via twitter @LukasGentele or email: lg AT devspace.cloud

Looking forward to hearing from you!

Tweet
Recent Posts
  • 1. Create Rails Project
  • 2. Containerize Project
    • Bonus: Add Postgres Database
  • 3. Choose Kubernetes Cluster
  • 4. Develop Project
    • Generate Index Route
    • Extra: Add Posts
  • 5. Deploy Project
  • What's next?
Star
Don't miss new blog posts and subscribe here:
Subscriptions