鉄板すぎる話ですが、自分の手元で確かめたかったのでメモに残します。
- Alpine Linux を利用する
- RUN 命令などを削減する
- マルチステージビルド
- 全部盛り
何もしない状態
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
参考