Even though all the rage today is about GO, Ruby is still a widely used and relevant language. For me, personally, it’s still pretty much the most enjoyable language of all. Thankfully I had recently the chance to work on a Ruby on Rails project. Today I would love to share with you my experience while deploying the project to OpenShift 3.
Do not expect anything special or complex. There are no weird catches, however I still thought it might be useful to put together a quick writeup on the needed steps.
First of all you should be a bit familiar with OpenShift 3. From the previous version we made a huge leap and the platform is now based on Docker and Kubernetes. Eventually, it is possible to share your custom build Docker images and have them run by OpenShift. That is not, however, what I am going to discuss today, as we are going to build the Docker image inside OpenShift from your source code.
Source to Image
One of the challenges OpenShift had to solve was the process of transforming raw source code into deployable Docker images. For this popular use-case we came up with a nice tool called Source-to-Image (S2I). This tool introduces one new concept called Builder image. Builder images are Docker images that know how to convert particular technology/framework/language into deployable state.
I guess an example might help us here:
Imagine you have some Ruby on Rails application and you want to convert the application into a Docker image. With S2I, there is a Builder image tweaked for Ruby application that is going to take a look at your code and will do the regular deployment steps.
If there is a Gemfile, the image runs
bundle install
If there is Gemfile.lock then it runs bundle
install --deployment
To install your dependencies.
In case the application is Ruby on Rails application, the image pre-compiles your assets. Eventually many other steps may be added.
The great thing about the Docker images is that the Builder image is actually a set of 3 executables, in most cases shell scripts, packed into a Docker image. Therefore, it is pretty simple to build custom Builder images. We are going to use a Builder image for Ruby 2.2 on CentOS 7.
OpenShift 3 API
OpenShift exposes its features as an API that consumes JSON or YAML files. OpenShift also provides command line tools and web interface, that can hide pretty much all of those files. A nice and simple user-interface with a better user experience is also available.
However, at this time not all features are exposed to the public. Therefore, sometimes it’s needed to jump down to the API and do some things manually. This will change in the near future, as we are hard at work on polishing the user experience and user interfaces.
Setting up image streams
Image stream is an important concept in OpenShift. According to some studies 75% of all Docker images on Docker Hub are vulnerable to some well known attacks, and 30% contains high-priority vulnerabilities.
As you may know, Docker images contain the whole user land, or pretty much everything that is required from the distribution to run the application, except the Kernel. This includes tools, libraries and many other things. This is a lot of code, that may possibly contain a problem that may allow some kind of attack on the application.
Sooner or later you will find yourself in a situation, when there is a fix required for your image or one of the parent images your own image is using. So, whenever your upstream image gets a security update, you need to rebuild your application image to consume the changes. This is one of the problems image streams are trying to tackle. Using image streams, the platform knows what images are there and whenever a new image is added into the stream, the platform can react by rebuilding all downstream images to propagate the fix.
OpenShift 3 comes by default with Ruby 2.0 builder, however there is also one for Ruby 2.2 published on Docker Hub, and there is no reason for you not to be able to use it. To do that we will define new image stream in OpenShift that is going to reference that image from Docker Hub. For this task we need to jump down to the API and do it manually.
Create new file called imageStream.json with this content
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "ruby-22-centos7"
},
"spec": {
"dockerImageRepository": "openshift/ruby-22-centos7:latest",
"tags": [
{
"name": "latest",
"annotations": {
"description": "Ruby 2.2 STI image",
"tags": "builder,ruby",
"supports": "ruby",
"version": "1.0"
}
}
]
}
}
Then instruct OpenShift to process it.
oc create -f imageStream.json
Let us talk about the JSON file for a second. We are describing an ImageStream and are using version 1 of the API. We want the image stream to be known as ruby-22-centos7 and the image stream should link to the image openshift/ruby-22-centos7 in the Docker repository. We also add some tags to let OpenShift know that this is a builder image, so the platform can advertise this builder image in the future.
Now we have a Ruby 2.2 Builder image defined in OpenShift and we can start using it.
Deploying the application
With OpenShift 2 there was a git repository that provided a simple way to transfer application source code to the OpenShift platform. With OpenShift 3, the source code repository is not there, but you can use any possible git repository provided. For example you can use Gitlab or Github.
To link your application to OpenShift you run a command like this
oc new-app path/to/source/code --image-stream=ruby-22-centos7 --name=myapp
The command will check if there is a git repository configured, and will use the remote from that repository to configure the source from where OpenShift will download your source code for the build. We also specify that we want to use Ruby 2.2 for building the application and the application is going to be named myapp.
Once you have your application defined, you simply trigger the build process.
oc start-build myapp
OpenShift is going to fetch the source code, setup the Builder image, build your application image and also will deploy the newly created image.
Now, if you look at the running containers in OpenShift
oc get pods
You should see a line starting with myapp-(#number)-(some hash) and that is your application running in OpenShift.
Deploying application from non-public repositories
Many times you will find yourself in a situation where you can not use public repository for your code, e.g. free public hosted git repository at Github, because your code is private. In such case, you simply follow the previous steps, but the build is going to fail, because OpenShift will not be able to download the source code as it will not have the credentials to authenticate itself against the git repository.
But do not worry, there is a solution.
You can upload some private key to OpenShift and authorize its public counterpart at the git hosting, and with those in place, OpenShift will be able to access your private git repository. I do not want to go into too many details here, you can read more in the documentation linked earlier.
First, generate an RSA key that is going to be uploaded to OpenShift (be careful not to overwrite your current keys)
ssh-keygen -t rsa -C "my_secret_key_for_OpenShift"
Then, you upload the key to OpenShift:
oc secrets new secret_for_accessing_scm ssh-privatekey=$HOME/.ssh/
After that, you provide this key to the builder service account
oc secrets add serviceaccount/builder secrets/secret_for_accessing_scm
Finally, you need to update your build configuration
oc patch buildConfig myapp -p '{"spec":{"source:{"sourceSecret":{"name":"secret_for_accessing_scm"}}}}'
Conclusion
Today we discussed the basic steps to deploy your Ruby application to OpenShift 3. In the next blog post, we are going to take a look on how to add additional services (MySQL, PostgreSQL, etc.) and link them together.
Categories
OpenShift Container Platform, OpenShift Dedicated, OpenShift Online