So you want to create a Dockerfile that you can build and deploy to production and run as your development environment? You could build a bunch of layers, but that quickly turns into a mess requiring multiple build scripts. The easier option is to use the ARG
directive in your Dockerfiles.
Here’s the skinny:
# Example Rails Dockerfile.
FROM ruby
# ARGS default to production settings. They are over-ridden
# by the compose file for development and CI environments.
ARG BUNDLE_WITHOUT="development:test"
ARG APT_DEV_PACKAGES=""
RUN apt-get -q update \
&& apt-get -q -y install \
git \
libxslt1-dev libxml2-dev \ # For nokogiri
make \
g++ \
libmysqlclient-dev \ # For MySQL gem
curl \
${APT_DEV_PACKAGES} \
&& apt-get -q -y clean \
&& rm -rf /var/lib/apt/lists
WORKDIR /app
COPY Gemfile* /app/
# Bundler ENV var http://bundler.io/man/bundle-config.1.html.
ENV BUNDLE_WITHOUT=${BUNDLE_WITHOUT}
RUN bundle install \
--retry 3 \
--jobs 4 \
--binstubs \
CMD bundle exec rails server
If you build this image without any build-args
, you’ll end up with a production-ready container.
The trick is how you set this up in your docker-compose.yml
file:
version: '2'
services:
rails:
build:
context: .
args:
BUNDLE_WITHOUT: ""
APT_DEV_PACKAGES: "qt5-default libqt5webkit5-dev phantomjs xvfb nodejs redis-tools dbus mysql-client"
When you run docker-compose build
you’ll end up with a development image with all the right gems and apt packages installed.
A year ago I decided that I’d only run development environments inside Docker containers so that I’d Learn The Hard Way™ all of the workflow pitfalls before rolling it out to the rest of the crew at Poll Everywhere. I’ve got a few more articles in the works that uncover more Docker development environment naunces that I’ll tweet from @bradgessler.