Glorious Future

Dockerizing Apps

We are in a time of great oppression, yet we sit at the doorstep of utopia.  We, as the true heirs of the earth, must be the driving force that pushes this door open to the glorious future that is now within our reach.

- Joseph Stalin 

Why Dockerize?

  • Bundles an application and all it's dependencies in one place.
  • Creates a standard unit for deployment, regardless of what kind of application.

Operating System

Runtime (Ruby/Java)

Libraries (Gems/Jars)

Application

Build

Run

Rules for App Dockerizability

  1. Accept configuration as environment variables
  2. Log to standard out
  3. Avoid writing to disk

Run

WORKERS=5

PORT=8080

App

Logs

Disk

How to Build the Image

  1. Create a Dockerfile
  2. Setup CircleCI to Build
    1. circle.yml
    2. Environment variables in CircleCI

my_app/

   config/

   lib/

   spec/

   circle.yml

   Dockerfile

DOCKER_USER
DOCKER_EMAIL

DOCKER_PASSWORD

(DOCKER_REPOSITORY)

Dockerizing for Ruby

  • Use `ENV.fetch('MY_ENV_VAR')` to read config
    • Will fail if ENV doesn't have an entry and no default is given.
    • Cast to the type you want `Integer(ENV.fetch('NUM'))`
    • Specify a default ENV.fetch('NAME', 'bob')
  • Write to standard out
    • If Rails, include rails_12factor in your Gemfile
      • Also allows rails app to serve static assets
    • Tell your logger to user STDOUT
      •  
  • Add gz_release to Gemfile
    • Load the rake tasks in your Rakefile
      •  
logger = Logger.new(STDOUT)
require 'gz_release'
GzRelease::Tasks.install(image_name: 'gazelle/wit')

Use Foreman

  • Add foreman to your Gemfile
  • Add a Procfile with the command to start your app
    • a
  • Can now start the app with 
web: puma -C ./config/puma.rb
foreman start web

Add a Dockerfile

FROM gazelle/ruby:2.2.3
MAINTAINER Gazelle
CMD foreman start web
ENV DATABASE_URL=--CHANGEME-- \
    PORT=8080 \
    WORKERS=5
FROM ruby:2.2.3

###### Create user
ENV user app
ENV home /home/app/
ENV group app
ENV PATH /home/app/bin:$PATH

RUN mkdir -p $home \
 && groupadd -r $group -g 777 \
 && useradd -u 666 -r -g $group -d $home -s /sbin/nologin -c "Docker image user" $user \
 && chown -R $user:$group $home
WORKDIR $home

###### App Setup
# gems may be cacheable, so do minimal work first to
# install gems to minimize cache bust.
ENV PORT 8080
ONBUILD COPY Gemfile $home
ONBUILD COPY Gemfile.lock $home
ONBUILD RUN bundle install --path=vendor/bundle --jobs=4 --retry=3 --deployment --binstubs
ONBUILD COPY . $home
ONBUILD RUN chown -R $user:$group $home
ONBUILD USER $user

EXPOSE 8080
CMD foreman start web

Add a circle.yml

machine:
  services:
    - docker
checkout:
  pre:
    - git config --global user.email "circleci@gazelle.com"
    - git config --global user.name "Gazelle CircleCI Bot"
deployment:
  all:
    branch: /^(?!(master|dev)).*$/
    commands:
      - bundle exec rake release:build
      - bundle exec rake release:push:branch
  master:
    branch: master
    commands:
      - bundle exec rake release:build
      - bundle exec rake release:push:timestamp
      - bundle exec rake release:push:release
  dev:
    branch: dev
    commands:
      - bundle exec rake release:build
      - bundle exec rake release:push:latest

Setup Circle Project

The Building Blocks

  • Docker Ruby
    • https://github.com/docker-library/ruby/blob/0cdec78d89e33750a4b796bd2c748f0d5a1ae654/2.2/Dockerfile
  • Docker Build Dependencies
    • https://github.com/docker-library/buildpack-deps/blob/master/jessie/Dockerfile
    • https://github.com/docker-library/buildpack-deps/blob/master/jessie/scm/Dockerfile
  • Gazelle Ruby
    • https://github.com/secondrotation/ruby_app
  • Gazelle Release
    • https://github.com/secondrotation/gz_release

Ruby App Examples

  • WIT
    • https://github.com/secondrotation/where_is_tudor
  • WAR
    • https://github.com/secondrotation/war
  • tutum_rewind
    • https://github.com/secondrotation/tutum_rewind

Java Time

Questions?

Dockerizing Apps

By blatyo

Dockerizing Apps

  • 819