LoginSignup
1
0

More than 1 year has passed since last update.

Rails の Dockerイメージを軽量化してみる

Last updated at Posted at 2021-08-09

鉄板すぎる話ですが、自分の手元で確かめたかったのでメモに残します。

  1. Alpine Linux を利用する
  2. RUN 命令などを削減する
  3. マルチステージビルド
  4. 全部盛り

何もしない状態

Docker ドキュメント を参考に作成。

FROM ruby:2.6.8
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem install bundler:2.2.16 
RUN bundle install
COPY . /app

COPY dockerfiles/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

サイズは1GB超え。

$ docker image ls
REPOSITORY         TAG               IMAGE ID       CREATED          SIZE
vocabook_api_app   latest            005fb8bfbdae   4 minutes ago    1.11GB

Alpine Linux を利用する

Alpine Linux は、コンテナでよく登場する軽量な Linux ディストリビューション。
apk というパッケージマネージャを利用するため、サブコマンドやパッケージ名を修正する。

注意:
すでに Debian ベースで動かしているサービスをコンテナ化する場合などは、Debian ベースの軽量なディストリビューション(stretch や buster)の利用が推奨されます。

FROM ruby:2.6.8-alpine3.14
RUN apk update -qq && apk add --no-cache build-base postgresql-dev nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem install bundler:2.2.16 
RUN bundle install
COPY . /app

COPY dockerfiles/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

何もしない状態から 300MB 削減。

$ docker image ls
REPOSITORY         TAG               IMAGE ID       CREATED          SIZE
vocabook_api_app   latest            24268673b3c8   43 seconds ago   799MB

RUN 命令などを削減する

RUN や COPY などの命令によってレイヤと呼ばれる中間イメージが作成される。
命令数を減らすことで生成されるレイヤを削減し、イメージの軽量化を図る。

FROM ruby:2.6.8
RUN apt-get update -qq && \
    apt-get install -y build-essential libpq-dev nodejs && \
    mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock /app/
RUN gem install bundler:2.2.16 && bundle install
COPY . /app

COPY dockerfiles/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

この程度の命令数ではサイズは変わらず。

$ docker image ls
REPOSITORY         TAG               IMAGE ID       CREATED              SIZE
vocabook_api_app   latest            3b3100aef7b1   About a minute ago   1.11GB

マルチステージビルド

bundle installで分けている記事があったので参考に試してみる。
パッケージをインストールするステージ、そのパッケージをコピーして持ってくるステージに分ける。

FROM ruby:2.6.8 AS builder
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem install bundler:2.2.16 
RUN bundle install

FROM ruby:2.6.8 AS runner
RUN apt-get update -qq && apt-get install -y libpq-dev nodejs
RUN mkdir /app
WORKDIR /app
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . /app

COPY dockerfiles/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

何もしていない状態から 20MB 程度減らすことができた。

$ docker image ls
REPOSITORY         TAG               IMAGE ID       CREATED          SIZE
vocabook_api_app   latest            376df67aec60   35 minutes ago   1.09GB

history コマンドでレイヤのサイズを見てみると、確かに 20MB くらい削減されている。

上:何もしないとき | 下:マルチステージビルド

<missing>      4 hours ago          RUN /bin/sh -c bundle install # buildkit        103MB     buildkit.dockerfile.v0
<missing>      11 minutes ago   COPY /usr/local/bundle /usr/local/bundle # b…   86.4MB    buildkit.dockerfile.v0

マルチステージビルドは、コンパイルしてバイナリを生成するようなケースだと分かりやすく効果が出そう。

全部盛り

FROM ruby:2.6.8-alpine3.14 AS builder
RUN apk update -qq && \
    apk add --no-cache build-base postgresql-dev nodejs && \
    mkdir /app
WORKDIR /app
COPY Gemfile Gemfile.lock /app/
RUN gem install bundler:2.2.16 && bundle install

FROM ruby:2.6.8-alpine3.14 AS runner
RUN apk update -qq && \
    apk add --no-cache postgresql-dev nodejs && \
    mkdir /app
WORKDIR /app
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . /app

COPY dockerfiles/rails/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

CMD ["rails", "server", "-b", "0.0.0.0"]

めっちゃ小さくなった。何もしない状態の半分近くまで小さくなっている。

$ docker images
REPOSITORY         TAG               IMAGE ID       CREATED             SIZE
vocabook_api_app   latest            4aebe416674b   2 minutes ago       588MB

history を見てみると、apk addのところで差分が出ていそうなので、build-base を最終イメージに持ってこなかったのが良かったみたい。

<missing>      6 minutes ago   RUN /bin/sh -c apk update -qq &&     apk add…   354MB     buildkit.dockerfile.v0
<missing>      6 hours ago     RUN /bin/sh -c apk update -qq && apk add --n…   547MB     buildkit.dockerfile.v0

参考

1
0
0

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
1
0