Skip to content

Latest commit

 

History

History
156 lines (97 loc) · 5.26 KB

File metadata and controls

156 lines (97 loc) · 5.26 KB

Dockerize a Rails App (for kubernetes)

Create a new rails app (or use an existing one). Add a Dockerfile docker build and docker push kubectl run

Step by Step

1. rails new

rails new myapp
cd myapp

We'll be using postgres as the database, so make sure they are in your Gemfile (vi Gemfile):

vi Gemfile

...
gem 'pg'

bundle

Now do something that would require a database, and respond on "/". Be creative, or copy from https://github.com/engineyard/k8sapp

a model:

bundle exec rails generate model HitCounter hits:integer
cp ~/kubernetes-workshop/code-snippets/hit_counter.rb app/models/hit_counter.rb

a controller:

bundle exec rails generate controller Slash
cp ~/kubernetes-workshop/code-snippets/slash_controller.rb app/controllers/slash_controller.rb

a route:

cp ~/kubernetes-workshop/code-snippets/routes.rb config/routes.rb

If you've just copied verbatim up to this point, maybe do at least SOMEHTING custom by modifying the output, just be sure it's YOUR app that's being run and not one of the images generated by the tutorial authors.

vi app/controllers/slash_controller.rb

...
render json: {"Hit Count" => HitCounter.hits, "Owner" => "Leowen"}
...

1.5 Test run with puma (optional)

You should be able to run your app locally

bundle
bundle exec rake db:migrate

Output the URL to open in your web browser

echo $(curl -s http://169.254.169.254/latest/meta-data/public-hostname):5000

Start puma sever on port 5000

bundle exec puma -p 5000

If you were doing this on your local dev machine you'd pop open a browser and visit localhost:5000, but since you are doing this on the "bridge" box you'll need to point your browser at the amazon public hostname plus port 5000.

2. Dockerfile

Our app will run inside a container, so we need a Dockerfile that defines how to setup it's OS-level dependencies and ends with what command to run (bundle exec puma -p 5000)

vi Dockerfile

Here's a starting point:

#The base image, with ruby pre-installed
#see: https://hub.docker.com/_/ruby/
FROM ruby:2.3

# Install dependencies:
# - build-essential: To ensure certain gems can be compiled
# - nodejs: Compile assets
# - libpq-dev: Communicate with postgres through the postgres gem
# - postgresql-client-9.4: In case you want to talk directly to postgres
RUN apt-get update && apt-get install -qq -y build-essential nodejs libpq-dev postgresql-client-9.4 --fix-missing --no-install-recommends

# Set an environment variable to store where the app is installed to inside
# of the Docker image.
ENV INSTALL_PATH /app
RUN mkdir -p $INSTALL_PATH

# This sets the context of where commands will be ran in and is documented
# on Docker's website extensively.
WORKDIR $INSTALL_PATH

# (optional/recommended) Environment variables for Dockerized production Rails apps
# ENV RAILS_ENV production
# ENV RAILS_SERVE_STATIC_FILES true
# ENV RAILS_LOG_TO_STDOUT true

# Ensure gems are cached and only get updated when they change. This will
# drastically increase build times when your gems do not change.
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
RUN bundle install --deployment

# Copy code from working directory outside Docker to working directory inside Docker
COPY . .
#Sometime an extra bundle call is needed to install binaries / native extensions
RUN bundle install --deployment

# Precompile assets
RUN bundle exec rake DATABASE_URL=postgresql:does_not_exist assets:precompile

# The default command to start the Unicorn server.
CMD bundle exec puma -p 5000

Next we'll build the docker image.

IMPORTANT This is the step where you want to make sure you are not consuming conference bandwidth. If you have been developing your app locally and not on the "bridge" box, now is the time to push it up there. Building and pushing docker images consumes significant bandwidth, but if we do it while SSH'd into our "bridge" box we're consuming bandwith on Amazon EC2 instead of locally.

Connect Docker daemon to docker hub using the login command:

docker login

Replace jacobo in these next few commands with your account name on Docker hub (hub.docker.com), and myapp with the name of your rails app.

Build a docker image and tag it:

docker build -t jacobo/myapp .

Push the tagged image to docker hub:

docker push jacobo/myapp

2.5 Test run with docker (optional)

You should be able to run your app locally inside docker with:

sudo docker run -d -p 5000:5000 jacobo/myapp

Needs to be torn-down, for example:

$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
929f6f34b1a1        jacobo/myapp        "/bin/sh -c 'bundle e"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   romantic_volhard

$ sudo docker kill 929f6f34b1a1

3 Deploy on Kubernetes

Create a deployment (specify your own app name and your own image):

kubectl run myapp --image=jacobo/myapp --port 5000

Refer back to Pods & Services and Secrets & Environment Variables for steps to productionize your app.