Deploy Ruby on Rails to Kubernetes
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
.

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:

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 prefixdevspace enter --
, we tell DevSpace to run thisrails
command inside a container within Kubernetes instead of executing it on the local machine. You could also run any otherrails
,npm
orbundle
command within the container by just addingdevspace 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:
- Replace "Welcome#index" with "Hello World" text inside the file
app/views/welcome/index.html.erb
- 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:
- Go to this URL: http://localhost:3000/posts
- Add posts and see how they are persisted to the database.
- 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!