If you want to follow along you’ll need Ruby (version ~> 2.2) with bundler installed. I use Oh my gems to manage gemsets and rbenv to manage different versions of Ruby. You’ll also need the gcloud utility installed.
Creating A Sinatra App
This is going to be a very bare bones Sinatra application. No database. No views. It will have a single HTTP endpoint. Start with a basic Gemfile and then use bundler to install the gems.
Now for the absolute bare minimum Sinatra application:
Test that everything is working by running
web.rb and then accessing it from a browser.
Google Container Engine Set Up
To run the application on Google Container Engine there is some basic setup necessary.
Create a project and Enable APIs
First, create a project on http://cloud.google.com/console. Once the project is created enable the Container Engine API, the Compute Engine API, and the Cloud Storage API. Some of these APIs may already be enabled.
Initialize your development environment
The next step is to initialize your gcloud environment. Use
gcloud init to log in, set your project, and your compute zone. Since I switch projects frequently I find it easier to create a custom configuration in gcloud for each project.
Once gcloud is initialized it is time to create the container cluster.
This might take a few minutes. Once that is done you can push your application to Google Container Engine.
Containerize the Application
To deploy this tiny little app on Google Container Engine it needs to be packaged as a Docker container. I found a basic Dockerfile for a Sinatra application here: https://rubyplus.com/articles/2461.
FROM ruby:2.2.1 MAINTAINER Aja Hammerly <email@example.com> RUN apt-get update && \ apt-get install -y net-tools # Install gems ENV APP_HOME /app ENV HOME /root RUN mkdir $APP_HOME WORKDIR $APP_HOME COPY Gemfile* $APP_HOME/ RUN bundle install # Upload source COPY . $APP_HOME # Start server ENV PORT 8080 EXPOSE 8080 CMD ["ruby", "web.rb"]
This container extends the officially maintained Ruby container so the only additional work to be done is specific to this application: installing gems, copying the application source, and then starting the server. I started my server on port 3000 since that is common for Ruby web applications. Once the application is deployed to Google Cloud mapping to a more conventional port (like 80) is straightforward.
Building and Testing Locally
Now to build the Docker image and test the app locally. First build the image:
docker build -t username/sinatra .
Then run the app:
docker run --rm -p 8080:8080 username/sinatra
To see the app running in the browser you can get the IP address from Docker Machine.
docker-machine ip default
Build the Container and Push it to Google Container Registry
In order to deploy the container to Container Engine the container image needs to be in an accessible place. Google Container Registry puts the container image in a Google Cloud Storage in the project. This allows you to limit access to the container image. The following commands build the docker image, tag it, and then push the tagged image to Google Container Registry.
docker build -t gcr.io/your-project-id/sinatra:v1 . gcloud docker push gcr.io/your-project-id/sinatra:v1
If you are on a Mac or Windows machine and run into trouble with “
gcloud docker push” try restarting Docker Machine. I ran into this issue since I had left Docker Machine running for several days. A restart fixed the problem.
Deploying with Kubernetes
A simple Kubernetes deployment is straight forward. In the series on deploying Rails via Kubernetes, I used a very simple pod, controller, and service. That isn’t the simplest way to deploy an application via Kubernetes though. For the Sinatra app we’ll make it even simpler.
kubectl run sinatra --image=gcr.io/your-project-id/sinatra --port=8080 kubectl expose deployment sinatra --type="LoadBalancer"
The first command starts up the Sinatra container in the cluster created earlier. (It actually creates a replication controller with a single replica.) The second command creates a load balancer that allows access to the Sinatra container. (The load balancer is actually a service in Kubernetes parlance.) To get the IP address where the application is running use
kubectl get services sinatra
That command will list an external IP that you can use to access the Sinatra application on port 8080. That’s it. From nothing to a Sinatra app running in the cloud shouldn’t take more than an hour.