Thursday, 8 January 2015

Docker: Creating ruby 2.2.0, mysql and rails images

For the purposes of this post, I'm assuming you have a private repository with the address 10.0.0.1:5000.

In this example, you will notice a distinct similarity in the build scripts.
Hmm.
Funny that.
I created a tool sleet which is like fleet but for single server installs.
So that is the essence of those build scripts.
If I have time somewhere in my aging schedule and downright ludicrous deadlines, I'll open source it.

This creates 4 images in your private repo.

- debian which is an instance of jessie with various compilers etc installed.
- ruby-2.2.0 compiled from source
- mysql-ruby-2.2.0 with the build dependencies
- rails-2.2.0 from all of the above

The purpose was to get an image that can be used for `rails-api` micro services that builds and deploys ultra-fast.
This is done by pre-installing the most commonly used gems into the `rails-2.2.0` image.

Then when a build is done that inherits from the `rails-2.2.0` image, the `bundle install` simply uses the local gems and doesn't have to go off to any external gem sources.
The bundle output shows `Using` instead of `Installing` the latter of which involves snarfing gems off the web and purhaps compiling things.


First up, here's the tree you'll be creating:

.
├── debian
│   └── jessie
│       ├── Dockerfile
│       └── build.sh
├── mysql
│   └── 2.2.0
│       ├── Dockerfile
│       └── build.sh
├── rails
│   └── 2.2.0
│       ├── Dockerfile
│       ├── build
│       │   └── Gemfile
│       └── build.sh
└── ruby
    └── 2.2.0
        ├── Dockerfile
        └── build.sh

Here are the files:

debian/jessie/Dockerfile

FROM debian:jessie

MAINTAINER Your Name 

ENV REFRESHED_AT 2015-01-08

RUN apt-get update \
  && apt-get install -y --no-install-recommends \
    git curl procps \
    autoconf build-essential \
    libbz2-dev libcurl4-openssl-dev libffi-dev libssl-dev libreadline-dev libyaml-dev \
    zlib1g-dev --no-install-recommends \
  && rm -rf /var/lib/apt/lists/*

debian/jessie/build.sh

#!/bin/sh

IMAGE=debian

export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=${HOME}/.boot2docker/certs/boot2docker-vm
IMAGE_REPO=10.0.0.1:5000

echo "------------------------------------------------------------------------"
echo " ENVIRONMENT"
echo "      DOCKER_HOST     ${DOCKER_HOST}"
echo "      IMAGE           ${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " ENVIRONMENT"
echo "      DOCKER_HOST     ${DOCKER_HOST}"
echo "      IMAGE           ${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " DELETING OLD IMAGES"
docker rmi ${IMAGE_REPO}/images/${IMAGE} ${IMAGE}
echo "========================================================================"
echo ""

set -e

echo "------------------------------------------------------------------------"
echo "BUILD"
docker build -t="${IMAGE}" .
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "IMAGES"
docker images | egrep "^${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "HISTORY"
docker history ${IMAGE}
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " TAG AND PUSH"
docker images | grep "^${IMAGE}"
sha=`docker images | grep "^${IMAGE}" | awk '{ print $3; }' | cut -f1`
echo "sha=${sha}"
docker tag ${sha} ${IMAGE_REPO}/images/${IMAGE}
docker push       ${IMAGE_REPO}/images/${IMAGE}
echo "========================================================================"
echo ""

ruby/2.2.0/Dockerfile

FROM 10.0.0.1:5000/images/debian

MAINTAINER Your Name 

ENV REFRESHED_AT 2015-01-08

ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.0

RUN apt-get update \
  && apt-get install -y bison ruby \
  && rm -rf /var/lib/apt/lists/* \
  && mkdir -p /usr/src/ruby \
  && curl -SL "http://cache.ruby-lang.org/pub/ruby/$RUBY_MAJOR/ruby-$RUBY_VERSION.tar.bz2" | tar -xjC /usr/src/ruby --strip-components=1 \
  && cd /usr/src/ruby \
  && autoconf \
  && ./configure --disable-install-doc \
  && make -j"$(nproc)" \
  && apt-get purge -y --auto-remove bison ruby \
  && make install \
  && rm -r /usr/src/ruby

# skip installing gem documentation
RUN echo 'gem: --no-rdoc --no-ri' >> "$HOME/.gemrc"

# install things globally, for great justice
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH
RUN gem install bundler \
  && bundle config --global path "$GEM_HOME" \
  && bundle config --global bin "$GEM_HOME/bin"

# don't create ".bundle" in all our apps
ENV BUNDLE_APP_CONFIG $GEM_HOME

CMD [ "irb" ]

ruby/2.2.0/build.sh

#!/bin/bash

IMAGE=ruby-2.2.0

export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=${HOME}/.boot2docker/certs/boot2docker-vm
IMAGE_REPO=10.0.0.1:5000

echo "------------------------------------------------------------------------"
echo " ENVIRONMENT"
echo "      DOCKER_HOST     ${DOCKER_HOST}"
echo "      IMAGE           ${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " DELETING OLD IMAGES"
docker rmi ${IMAGE_REPO}/images/${IMAGE} ${IMAGE}
echo "========================================================================"
echo ""

set -e

echo "------------------------------------------------------------------------"
echo " BUILD"
docker build -t="${IMAGE}" .
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "IMAGES"
docker images | egrep "^${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "HISTORY"
docker history ${IMAGE}
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " TAG AND PUSH"
docker images | grep "^${IMAGE}"
sha=`docker images | grep "^${IMAGE}" | awk '{ print $3; }' | cut -f1`
echo "sha=${sha}"
docker tag ${sha} ${IMAGE_REPO}/images/${IMAGE}
docker push       ${IMAGE_REPO}/images/${IMAGE}
echo "========================================================================"
echo ""

mysql/2.2.0/Dockerfile

FROM 10.0.0.1:5000/images/ruby-2.2.0

MAINTAINER Your Name 

ENV REFRESHED_AT 2015-01-08

ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.0

RUN buildDeps='libmysqlclient-dev'; \
      set -x \
      && apt-get update && apt-get install -y $buildDeps --no-install-recommends

CMD [ "irb" ]

mysql/2.2.0/build.sh

#!/bin/bash

IMAGE=ruby-2.2.0

export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=${HOME}/.boot2docker/certs/boot2docker-vm
IMAGE_REPO=10.0.0.1:5000

echo "------------------------------------------------------------------------"
echo " ENVIRONMENT"
echo "      DOCKER_HOST     ${DOCKER_HOST}"
echo "      IMAGE           ${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " DELETING OLD IMAGES"
docker rmi ${IMAGE_REPO}/images/${IMAGE} ${IMAGE}
echo "========================================================================"
echo ""

set -e

echo "------------------------------------------------------------------------"
echo " BUILD"
docker build -t="${IMAGE}" .
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "IMAGES"
docker images | egrep "^${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "HISTORY"
docker history ${IMAGE}
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " TAG AND PUSH"
docker images | grep "^${IMAGE}"
sha=`docker images | grep "^${IMAGE}" | awk '{ print $3; }' | cut -f1`
echo "sha=${sha}"
docker tag ${sha} ${IMAGE_REPO}/images/${IMAGE}
docker push       ${IMAGE_REPO}/images/${IMAGE}
echo "========================================================================"
echo ""

rails/2.2.0/Dockerfile

FROM 10.0.0.1:5000/images/debian-mysql-ruby-2.2.0

MAINTAINER Your Name 

ENV REFRESHED_AT 2015-01-08

ENV HOME /build
ENV RUBY_MAJOR 2.2
ENV RUBY_VERSION 2.2.0
ENV GEM_HOME /usr/local/bundle
ENV PATH $GEM_HOME/bin:$PATH

ADD ./build /build

WORKDIR /build

RUN bundle install --jobs 8

CMD [ "irb" ]
rails/2.2.0/build/Gemfile

source 'http://your.private.gem.server:9900'

# ---------------------------------------------------------------------------
# Always these
# ---------------------------------------------------------------------------
gem 'rails', '4.2.0'
gem 'mysql2'

gem 'thin'
gem 'foreman'

gem 'jsonapi-resources' # and/or roar

gem 'db_populate', git: 'https://github.com/ffmike/db-populate.git'

gem 'rack-cors'
gem 'activeresource'

gem 'jbuilder', '~> 2.0'
gem 'typhoeus'
gem 'etcd'
gem 'hutch'
gem 'elasticsearch'
gem 'searchkick'

gem 'therubyracer'
gem 'oj'

# ---------------------------------------------------------------------------
# Unused
# ---------------------------------------------------------------------------
# gem 'jquery-rails'
# gem 'turbolinks'
# gem 'bcrypt', '~> 3.1.7' # Use ActiveModel has_secure_password
# gem 'sass-rails', '~> 4.0.3'
# gem 'uglifier', '>= 1.3.0'
# gem 'coffee-rails', '~> 4.0.0'
rails/2.2.0/build.sh
#!/bin/bash

IMAGE=rails-2.2.0

export DOCKER_HOST=tcp://192.168.59.103:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=${HOME}/.boot2docker/certs/boot2docker-vm
IMAGE_REPO=10.0.0.1:5000

echo "------------------------------------------------------------------------"
echo " ENVIRONMENT"
echo "      DOCKER_HOST     ${DOCKER_HOST}"
echo "      IMAGE           ${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " DELETING OLD IMAGES"
docker rmi ${IMAGE_REPO}/images/${IMAGE} ${IMAGE}
echo "========================================================================"
echo ""

set -e

echo "------------------------------------------------------------------------"
echo " BUILD"
docker build -t="${IMAGE}" .
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "IMAGES"
docker images | egrep "^${IMAGE}"
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo "HISTORY"
docker history ${IMAGE}
echo "========================================================================"
echo ""

echo "------------------------------------------------------------------------"
echo " TAG AND PUSH"
docker images | grep "^${IMAGE}"
sha=`docker images | grep "^${IMAGE}" | awk '{ print $3; }' | cut -f1`
echo "sha=${sha}"
docker tag ${sha} ${IMAGE_REPO}/images/${IMAGE}
docker push       ${IMAGE_REPO}/images/${IMAGE}
echo "========================================================================"
echo ""
Enjoy. YMMV.

No comments:

Post a comment