(O+P)ut

アウトプット



(O+P)ut

エンジニアのアウトプット

【Docker】MultiStageBuildを用いたDockerfileによるイメージ作成

スポンサーリンク

はじめに

以下の記事にてコンテナイメージを作成する手法の一つとしてDockerfileを利用する方法について説明しました。

今回は、従来のDockerfileを利用した手法からDockerイメージのサイズを削減する機能であるmulti-stage buildについて解説します。主にライブラリ依存周りで利用されますが、もっとイメージしやすい簡単な例を用意しました。

想定ケース

例えばイメージに以下のように特定コマンド(今回はtree)の実行結果が欲しいとします。

$ tree / > /root/tree.txt

しかし初期イメージに入っていなければ、Dockerfileに以下のように書いてもコマンドがないため失敗します。

FROM ubuntu
RUN tree / > /root/test.txt

よって以下のようにすることで必要コマンドがインストールでき

FROM ubuntu
RUN apt-get update
RUN apt-get install -y tree
RUN tree / > /root/tree.txt

このDockerfileにて

$ docker build -t ubuntu/tree:1 .

treeの実行結果が格納されたイメージが作成できました。

想定ケースのイメージを削減する技がある

イメージのサイズを見ていきます。

$ docker image ls
REPOSITORY  TAG  IMAGE ID  CREATED  SIZE
ubuntu/tree  1  XX  XX  92.8MB
ubuntu  latest  XX  XX  64.2MB

当たり前ですがapt-getの分だけ元のイメージよりサイズが大きくなっています

この例にて欲しいのはtreeコマンドの結果のみであった場合に、いわゆる冒頭でエラーとなった

FROM ubuntu
RUN tree / > /root/test.txt

だけを実現した小さなイメージは作成できないのでしょうか?

それを実現するのがmulti stage buildです。

Multi Stage Buildのやり方

結論から言うとDockerfileに以下のように書きます。

FROM ubuntu as test
RUN apt-get update
RUN apt-get install -y tree
RUN tree /root > /root/tree.txt

FROM ubuntu
COPY --from=test /root /root
COPY --from=test /usr/bin/tree /usr/bin/tree

上で分かる通り、testという仮のイメージを作成しそこから/rootディレクトリだけをコピーしています。これがmulti-stage buildになります。
今回はついでにtreeコマンドもそのまま持ってきてみました。

それを実行すると以下のようになります。

$ docker build -t ubuntu/treeonly:1 .
....
Successfully built ...
Successfully tagged ubuntu/treeonly:1

確かにイメージファイルのサイズを確認すると

$ docker image ls
REPOSITORY  TAG  IMAGE ID  CREATED             SIZE
ubuntu/treeonly  1  xyz XX  64.3MB
ubuntu/tree  XX  XX  92.8MB
ubuntu  latest  XX  XX  64.2MB

かなり小さくなってます。

もちろんそのイメージからコンテナを起動すると、必要な結果ファイルは格納されておりtreeコマンドも利用できます。

$ docker run -t -i xyz 
root@xyz:~# ls /root/
tree.txt
root@xyz:~# which tree
/usr/bin/tree

終わりに

コンテナの起動速度はイメージの大きさに依存します。

例えばコンパイル前のファイルが巨大ではあるもののコンパイル後のファイルだけイメージにとり入れたい場合など、応用例は多い機能なので覚えておくとどこかで役立つと思います。

ご参考になれば幸いです。