Skip to content

Instantly share code, notes, and snippets.

@martijn
Created January 26, 2021 12:09
Show Gist options
  • Save martijn/30acdb1c7755638371a024bcb7e0a25c to your computer and use it in GitHub Desktop.
Save martijn/30acdb1c7755638371a024bcb7e0a25c to your computer and use it in GitHub Desktop.
Ruby on Rails deployment Dockerfile
# This multi-stage Dockerfile will use the full ruby image during build phase
# after this it wil build the deployment image based on the slim ruby container,
# copying over all artifacts from the build phase.
#
# The deployer image will not include a Javascript runtime and will come in at
# under 200MB for an average Rails application.
ARG BUILDER_FROM_IMAGE=ruby:3.0
ARG DEPLOY_FROM_IMAGE=ruby:3.0-slim
ARG NODE_VERSION 14.15.4
ARG YARN_VERSION 1.22.5
FROM $BUILDER_FROM_IMAGE as builder
# Install Node and Yarn
RUN set -ex \
&& for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
77984A986EBC2AA786BC0F66B01FBB92821C587A \
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
4ED778F539E3634C779C87C6D7062848A1AB005C \
A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
B9E2F5981AA6E0CD28160D9FF13993A75599653C \
; do \
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
RUN set -ex \
&& for key in \
6A010C5166006599AA17F08146C2130DFD2497F5 \
; do \
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz
# /app is where our app will live
WORKDIR /app
# Bundle
COPY Gemfile /app
COPY Gemfile.lock /app
RUN bundle install -j 4 --without development test
# Yarn packages
COPY package.json /app
COPY yarn.lock /app
RUN yarn install --prod
# Copy app
COPY . /app
# Compile webpack assets
RUN RAILS_ENV=production SECRET_KEY_BASE=1 rails webpacker:compile && ln -s /app/public/packs /app/public/packs-test
# Build our final deployment image
FROM $DEPLOY_FROM_IMAGE AS deploy
WORKDIR /app
ENV RAILS_ENV=production RUBYOPT=-W:no-deprecated RAILS_LOG_TO_STDOUT=1
# Alternatively, set rails as entrypoing
CMD ["rails", "server"]
# Install runtime dependencies
RUN set -ex; \
apt-get update; \
apt-get install -y --no-install-recommends \
libpq5 libjemalloc2 imagemagick \
; rm -rf /var/lib/apt/lists/*
# Use jemalloc to save some memory usage
ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2
# Run as a non-priviledged user
RUN groupadd --gid 32767 rails \
&& useradd -s /bin/bash --uid 32767 --gid 32767 -m rails \
&& chown -R rails:rails /app
USER 32767
# Copy over app, bundle and assets
COPY --chown=32767:32767 . /app/
COPY --from=builder --chown=32767:32767 /usr/local/bundle /usr/local/bundle
COPY --from=builder --chown=32767:32767 /app/public/ /app/public/
# Done!
@martijn
Copy link
Author

martijn commented Jan 26, 2021

Running CI tests on the deployment image is easy, simply execute a bundle install --with test in the container before running your tests to create a correct build-test-deploy pipeline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment