経緯
Dockerfile を何度も編集して apt-get install していると、
パッケージのダウンロードに大きく時間を喰ってると体感することが多かった。
特に既存のイメージを継承しない新しいイメージを作るときは、
git のような基本的なパッケージまで再取得する。
ミラーかキャッシュか
かといって apt-mirror を使ったフルミラーを建てるのもなかなか手軽ではないと感じたので、
apt-cacher-ng でキャッシュ用のプロキシサーバを建てることにした。
apt-cacher-ng では取得したパッケージのみをキャッシュするので、
apt-mirror のように導入初期に大量にパッケージを取得する必要はない。
自分の使用範囲では apt-cacher-ng の方が合っているので apt-cacher-ng を選択した。
きっと適切な使い分けがあるのだろうと思う。
Docker のサイトにもあった
実は Docker のサイトにも apt-cacher-ng 用の Docker イメージを作る方法が紹介されているので、
apt-cacher-ng プロキシサーバの構築も Docker で行った。なので構築は 1 分でできてしまった。
実際に使ってみたところ
プロキシ設定をする場合としない場合でそれぞれ docker build にかかる時間を time コマンドで記録した。
docker による cache を含まずに測定するため、 docker build --no-cache
のように --no-cache
オプションで実行した。
プロキシ設定をする場合は 2 回 build を実行し、キャッシュが有効になる 2 回目の build を記録とした。
プロキシ設定をする場合は、次のような行を Dockerfile の apt-get 等が始まる前に書き加える。
RUN echo 'Acquire::http { Proxy "http://X.X.X.X:3142"; };' >> /etc/apt/apt.conf.d/01proxy
nginx だけをインストールしてみる場合
RUN apt-get update && apt-get install -y nginx
プロキシなし
real 1m4.797s
プロキシあり
real 0m19.806s
だいたい所要時間が 1/3 になっている。嬉しい。
もっとてんこもりにインストールしてみる。
次のような、大量のパッケージもインストールしてみた。
手持ちの環境を作るシェルスクリプト等からいくつか抜き出してまとめたもの。
Docker の常識的な使い方ではこんなにたくさんインストールすることはあまりないはず。
RUN apt-get update && \
apt-get install -y \
curl git vim tmux pv \
build-essential make ccache \
python-dev python-pip \
nodejs nodejs-dev \
libssl-dev \
zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev \
gfortran libopenblas-dev liblapack-dev g++ \
build-essential python3-tk tk-dev libpng12-dev \
libzmq3-dev \
freetds-dev freetds-bin tdsodbc \
pandoc \
r-base r-base-dev
プロキシなし
real 9m16.991s
プロキシあり
real 4m58.601s
こちらもすごく時間が短縮できた。 5 分減るのは大きい。
余談
以下は本題とは関係ないけど、一応触れておきたい話
DEBIAN_FRONTEND=nointeractive しよう
Ansible や Chef を使ってる人にもお馴染み。
Docker で apt-get する場合には
ENV DEBIAN_FRONTEND noninteractive
をつける習慣を持つと良い。
シェルでの人間が操作する場合以外はつけた方がいい。インタラクティブな質問をしてこなくなる ([y/N] みたいな)
他にもたとえば ncurses が立ち上がるのを防いだり。
なぜ複数の RUN ではなく 1 つの RUN に複数行書く
イメージ差分は Dockerfile のステートメントごとに記録される。
記録されたあとにファイルの削除を行っても、イメージのサイズは減少しない。
RUN の最後でクリーンアップが可能ならした方がいい。
apt-get clean
や rm
を使って不要なファイルを消してしまう方が健全。
(追加で apt-get する予定がないなら、 /var/lib/apt/lists/* ごと削除する手もある。 )
RUN apt-get update && \
apt-get install -y git curl nginx && \
apt-get clean &&
rm -rf /tmp/* /var/tmp/*
タイトル
書いたあとで気がついた。
タイトルの「建てたら幸せになった」は、前に読んだ ↓ を無意識に継承してしまっていた。