開発環境のDockerのビルド時間が約50倍早くなった
私たちのチームでは、開発時に devcontainer を利用することで、開発環境構築の手間を大幅に軽減しています。
しかし、devcontainer 起動時に発生する Docker イメージのビルドに、長いときには 8 分以上かかってしまい、毎朝のちょっとしたストレスになっていました。
この記事では、このビルド時間を わずか 9 秒程度 に短縮した対応についてご紹介します。
前提
今回の改善は、開発環境用の Dockerfile に対して実施したものです。
本番環境用には別途 Dockerfile が存在しており、開発環境用とは構成・目的が明確に分離されていることが前提です。
規模感
対象となるプロジェクトは Ruby on Rails で構築されており、rails stats によるコード行数は以下の通りです:
アプリケーションコード:18,868行
テストコード:31,203行
課題
開発環境用の Dockerfile のビルドに、長いときで 510 秒(約 8 分半)かかっていました。
対応
Rails プロジェクトではよく見られる形の Dockerfile になっており、Gemfile および Gemfile.lock をコピー後、bundle install を実行し、その後ソースコード全体を COPY する構成でした。
元のDockerfile(抜粋)
ARG RUBY_VERSION
ENV LANG C.UTF-8
FROM ruby:${RUBY_VERSION}
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=$USER_UID
ENV TZ=Asia/Tokyo
ENV APP_HOME=/usr/src/app
ENV RUBY_YJIT_ENABLE=1
RUN mkdir -p $APP_HOME
RUN apt-get update && apt-get install -y libvips sudo
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& echo "$USERNAME ALL=NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME\
&& chmod 0440 /etc/sudoers.d/$USERNAME
WORKDIR $APP_HOME
COPY Gemfile Gemfile.lock ${APP_HOME}/
RUN gem install bundler --no-document && \
bundle config jobs $(nproc) && \
bundle config build.puma "--with-cflags='-D PUMA_QUERY_STRING_MAX_LENGTH=30720'" && \
bundle install
COPY . $APP_HOME
USER $USERNAME
不要なステップの削除
開発環境ではソースコードをホスト側から Volume マウントして使用しているため、
COPY . . や bundle install はイメージビルド時に行う必要がないと判断し、これらのステップを削除しました。
対応後のDacokerfile(抜粋)
ARG RUBY_VERSION
ENV LANG C.UTF-8
FROM ruby:${RUBY_VERSION}
ARG USERNAME=devuser
ARG USER_UID=1000
ARG USER_GID=$USER_UID
ENV TZ=Asia/Tokyo
ENV APP_HOME=/usr/src/app
ENV RUBY_YJIT_ENABLE=1
RUN mkdir -p $APP_HOME
RUN apt-get update && apt-get install -y libvips sudo
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd -s /bin/bash --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& echo "$USERNAME ALL=NOPASSWD: ALL" > /etc/sudoers.d/$USERNAME\
&& chmod 0440 /etc/sudoers.d/$USERNAME
WORKDIR $APP_HOME
USER $USERNAME
結果
ビルド時間を定量的に比較するため、どちらも --no-cache オプションをつけて計測しています
状態 | ビルド時間 | コマンド |
---|---|---|
対応前 | 510.6秒 | docker build --no-cache |
対応後 | 8.9秒 | docker build --no-cache |
まとめ
Docker を使った開発環境では、Volume マウントを前提とする構成においては、ビルド時にソースコードのコピーや依存インストールを行わないことで、大幅な時間短縮が可能です。
普段あまり意識しない開発用 Dockerfile でも、少し見直すだけで日々の開発体験が大きく改善されることがあります。
この機会に、皆さんの環境も一度見直してみてはいかがでしょうか。
Discussion