Skip to content

Commit

Permalink
Add production stage to Dockerfile (#4053)
Browse files Browse the repository at this point in the history
* Restructure Dockerfile, add prod stage

* Add build target to docker-compose

* Further slim down prod image

* Allow logging to stdout in production
  • Loading branch information
phuongdh committed Jun 9, 2020
1 parent 2ebc209 commit b4f23b1
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 45 deletions.
7 changes: 5 additions & 2 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
.bundle
.git
.DS_Store
.gitignore
.env
tmp
Dockerfile
docker-compose.yml
docker-compose.yml
node_modules
public/packs
tmp
96 changes: 67 additions & 29 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
# Base stage for building gems
FROM ruby:2.5.5-stretch as base
ENV BUNDLER_VERSION 2.0.2
FROM ruby:2.5.5-stretch as bundle
RUN echo "deb http://deb.debian.org/debian stretch-backports main" >> /etc/apt/sources.list \
&& apt-get update && apt-get upgrade -y build-essential \
&& apt-get install -y --no-install-recommends \
cmake \
pkg-config \
zip \
git \
&& gem install bundler \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean

RUN mkdir -p /home/app/avalon
WORKDIR /home/app/avalon

COPY Gemfile ./Gemfile
COPY Gemfile.lock ./Gemfile.lock
RUN bundle config build.nokogiri --use-system-libraries \
&& bundle install --with aws development test postgres --without production

RUN gem install bundler -v "$(grep -A 1 "BUNDLED WITH" Gemfile.lock | tail -n 1)" \
&& bundle config build.nokogiri --use-system-libraries


# Build development gems
FROM bundle as bundle-dev
RUN bundle install --with aws development test postgres --without production

# Download stage takes advantage of parallel build

# Download binaries in parallel
FROM ruby:2.5.5-stretch as download
RUN curl -L https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz | tar xvz -C /usr/bin/
RUN curl https://chromedriver.storage.googleapis.com/2.46/chromedriver_linux64.zip -o /usr/local/bin/chromedriver \
&& chmod +x /usr/local/bin/chromedriver \
&& curl -L https://github.com/jwilder/dockerize/releases/download/v0.6.1/dockerize-linux-amd64-v0.6.1.tar.gz | tar xvz -C /usr/bin/ \
&& mkdir -p /tmp/ffmpeg && cd /tmp/ffmpeg \
&& chmod +x /usr/local/bin/chromedriver
RUN curl https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /chrome.deb
RUN mkdir -p /tmp/ffmpeg && cd /tmp/ffmpeg \
&& curl https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz | tar xJ \
&& cp `find . -type f -executable` /usr/bin/


# Dev stage for building dev image
FROM ruby:2.5.5-slim-stretch as dev
ENV BUNDLER_VERSION 2.0.2
# Base stage for building final images
FROM ruby:2.5.5-slim-stretch as base
RUN apt-get update && apt-get install -y --no-install-recommends curl gnupg2 \
&& curl -sL http://deb.nodesource.com/setup_8.x | bash - \
&& curl -O https://mediaarea.net/repo/deb/repo-mediaarea_1.0-6_all.deb && dpkg -i repo-mediaarea_1.0-6_all.deb \
&& curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
&& echo "deb http://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list

RUN apt-get update && apt-get install -y --no-install-recommends \
RUN apt-get update && apt-get install -y --no-install-recommends --allow-unauthenticated \
yarn \
nodejs \
lsof \
Expand All @@ -53,23 +54,60 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
mediainfo \
openssh-client \
zip \
imagemagick \
dumb-init \
&& gem install bundler \
&& curl https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /chrome.deb \
&& dpkg -i /chrome.deb || apt-get install -yf \
&& ln -s /usr/bin/lsof /usr/sbin/

ARG AVALON_BRANCH=develop
ARG RAILS_ENV=development
ARG BASE_URL
ARG DATABASE_URL
ARG SECRET_KEY_BASE

COPY --from=base /usr/local/bundle /usr/local/bundle
COPY --from=download /usr/local/bin/chromedriver /usr/local/bin/chromedriver
RUN useradd -m -U app \
&& su -s /bin/bash -c "mkdir -p /home/app/avalon" app
WORKDIR /home/app/avalon

COPY --from=download /usr/bin/ff* /usr/bin/
COPY --from=download /usr/bin/dockerize /usr/bin/

WORKDIR /home/app/avalon


# Build devevelopment image
FROM base as dev
COPY --from=bundle-dev /usr/local/bundle /usr/local/bundle
COPY --from=download /chrome.deb /
COPY --from=download /usr/local/bin/chromedriver /usr/local/bin/chromedriver
COPY --from=download /usr/bin/dockerize /usr/bin/
ADD docker_init.sh /

ARG RAILS_ENV=development
RUN dpkg -i /chrome.deb || apt-get install -yf


# Build production gems
FROM bundle as bundle-prod
RUN bundle install --without development test --with aws production postgres


# Install node modules
FROM node:8.17.0-stretch-slim as node-modules
RUN apt-get update && apt-get install -y --no-install-recommends git
COPY package.json .
COPY yarn.lock .
RUN yarn install


# Build production assets
FROM base as assets
COPY --from=bundle-prod --chown=app:app /usr/local/bundle /usr/local/bundle
COPY --chown=app:app . .
COPY --from=node-modules --chown=app:app /node_modules ./node_modules

USER app
ENV RAILS_ENV=production

RUN bundle exec rake assets:precompile SECRET_KEY_BASE=$(ruby -r 'securerandom' -e 'puts SecureRandom.hex(64)') \
&& cp config/controlled_vocabulary.yml.example config/controlled_vocabulary.yml


# Build production image
FROM base as prod
COPY --from=assets --chown=app:app /home/app/avalon /home/app/avalon
COPY --from=bundle-prod --chown=app:app /usr/local/bundle /usr/local/bundle

USER app
ENV RAILS_ENV=production
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ end
group :production do
gem 'google-analytics-rails', '1.1.0'
gem 'lograge'
gem 'puma'
end

# Install the bundle --with aws when running on Amazon Elastic Beanstalk
Expand Down
21 changes: 15 additions & 6 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,28 @@
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true

# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new

# Enable logging to both stdout and file, in more compact format
config.lograge.enabled = true
config.lograge.custom_options = lambda do |event|
{:time => event.time}
if ENV["RAILS_LOG_TO_STDOUT"].present?
logger = ActiveSupport::Logger.new(STDOUT)
logger.formatter = config.log_formatter
config.logger = ActiveSupport::TaggedLogging.new(logger)
else
config.lograge.enabled = true
config.lograge.custom_options = lambda do |event|
{:time => event.time}
end
end

# Use the lowest log level to ensure availability of diagnostic information
# when problems arise.
config.log_level = :info

# Suppress logger output for asset requests.
config.assets.quiet = true

# Prepend all log lines with the following tags.
# config.log_tags = [ :subdomain, :uuid ]

Expand All @@ -95,9 +107,6 @@
# Send deprecation notices to registered listeners.
config.active_support.deprecation = :notify

# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new

# Do not dump schema after migrations.
config.active_record.dump_schema_after_migration = false

Expand Down
9 changes: 5 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: '3.2'
version: '3.4'

volumes:
database:
Expand Down Expand Up @@ -77,8 +77,10 @@ services:
<<: *redis

avalon: &avalon
image: avalonmediasystem/avalon:7.0-slim-dev-20200225
build: .
image: avalonmediasystem/avalon:7.1-slim-dev-20200318
build:
context: .
target: dev
command: bash -c "/docker_init.sh && rails server -b 0.0.0.0"
depends_on:
- db
Expand All @@ -89,7 +91,6 @@ services:
- minio
environment:
- APP_NAME=avalon
- AVALON_BRANCH=develop
- SETTINGS__DOMAIN=http://localhost:3000
- BUNDLE_FLAGS=--with development postgres --without production test
- ENCODE_WORK_DIR=/tmp
Expand Down
4 changes: 0 additions & 4 deletions docker_init.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
#!/bin/bash

cd /home/app/avalon
export HOME=/home/app

# Workaround from https://github.com/yarnpkg/yarn/issues/2782
yarn install

bundle install && \
Expand Down

0 comments on commit b4f23b1

Please sign in to comment.