LoginSignup
38
30

More than 5 years have passed since last update.

Docker Multi-Stage BuildsでRailsのイメージを軽量化してみる

Last updated at Posted at 2017-12-19

はじめに

RailsのDockerイメージのサイズを半分以下にする事ができました!

Docker Multi-Stage Buildsとは

Docker17以降のバージョンでDockerfileにFrom句を複数書けるようになりました。
これがマジでヤバイ!

何がヤバイかというと、
複数のビルドしたイメージから必要なものだけをコピーできるということ。
ライブラリを展開する為に必要なツールのインストールなど行う場合が多々あるかと思いますが、最終的なイメージには不要なものもあるかと思います。

そういった不要なものを省く事が簡単にできます。
イメージはなるべくサイズを抑えるべきです。
イメージのビルド、デリバリの時間を圧縮でき、これはCI/CDの基本です。

Docker Multi-Stage Buildsに関しては、こちらの記事で詳しく解説されています。
Docker multi stage buildで変わるDockerfileの常識

Before And After

Rails用のdocker imageのサイズがどのくらい変わるか結果を先にお見せします。

Before

771MB

➜  rails_docker git:(master) ✗ docker images | grep web
railsdocker_web                latest              f2772a54bc64        54 seconds ago      771MB

After

355MB
なんと、半分以下のサイズになっています。

➜  rails_docker git:(master) ✗ docker images | grep web   
railsdocker_web                latest              bfeeacbc82e7        12 days ago         355MB

Dockerfile

続いてDockerfileのBefore, Afterを比較してみましょう。

Before

FROM ruby:2.3.2-alpine
ENV LANG ja_JP.UTF-8
RUN apk --update add --virtual build-dependencies \
    build-base \
    curl-dev \
    mysql-dev \
    linux-headers
RUN apk --update add \
    bash \
    nodejs \
    mariadb-dev \
    tzdata \
    && rm /usr/lib/libmysqld*

RUN gem install bundler

WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
ENV BUNDLE_JOBS=4
RUN bundle install
RUN apk del build-dependencies

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY . $APP_HOME

After

FROM ruby:2.3.2-alpine as builder
RUN apk --update add --virtual build-dependencies \
    build-base \
    curl-dev \
    mysql-dev \
    linux-headers
RUN gem install bundler
WORKDIR /tmp
COPY Gemfile Gemfile
COPY Gemfile.lock Gemfile.lock
ENV BUNDLE_JOBS=4
RUN bundle install
RUN apk del build-dependencies

FROM ruby:2.3.2-alpine
ENV LANG ja_JP.UTF-8
RUN apk --update add \
    bash \
    nodejs \
    mariadb-dev \
    tzdata \
    && rm /usr/lib/libmysqld*
RUN gem install bundler

WORKDIR /tmp
COPY --from=builder /usr/local/bundle /usr/local/bundle

ENV APP_HOME /myapp
RUN mkdir -p $APP_HOME
WORKDIR $APP_HOME
COPY . $APP_HOME

ここでポイントとなるのが、

FROM ruby:2.3.2-alpine as builder

と、

COPY --from=builder /usr/local/bundle /usr/local/bundle

です。
あと、FROMが2回登場している事がわかります。
最初のビルドでbuilderというエイリアスをつけており、そこから、

/usr/local/bundle

を次のビルドでコピーしています。
要は、最初のビルドではbundle installするだけが目的です。
その為のツールは全て不要です。

さいごに

Multi-Stage BuildsによってDockerイメージの軽量化ができました。
もちろん、Multi-Stage Buildsを利用せずとも軽量化はできます。
不要なファイルを手動で個別に削除していけば良いわけです。
しかし、Multi-Stage Buildsを使えば削除の手順を省く事ができるので、Dockerfileの見通しがよくなります。

更に、イメージの軽量化は可能ですが、細かいTipsは割愛します。

RailsのDockerイメージは肥大しやすいので、イメージサイズを少し意識してみてはいかがでしょうか?

快適なDockerライフを。

38
30
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
30