【少しでも楽してコンテナイメージを減らしたかった】コンテナイメージサイズを縮小するためにDive使ってイメージを分析してみた
こんばんわ、札幌のヨシエです。
コンテナを使用する時に必要となるものがコンテナイメージです。
このコンテナイメージは小さければ小さいほど正義として扱われ、この正義を通すために人はアレやコレやと試行錯誤を繰り返してコンテナイメージ縮小の旅に出ます。
その旅に持っていけると良いツールとしてDiveを試してみたので紹介させていただきます。
検証用コンテナイメージ
今回の検証は軽量コンテナイメージを元にして、Dockerfileによるレイヤーを重ねる形で動作を確認したいと思います。
利用したコンテナイメージはamazonlinux:latestを使用しました。
1 2 3 | % docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEamazonlinux latest dc34c260f454 5 weeks ago 163MB |
Diveのインストール
1 | brew install dive |
Diveの基本使用
以下のコマンドにてコンテナイメージを指定します。
1 | % dive amazonlinux:latest |
このような画面が表示されました。
画面のそれぞれを確認します。
①イメージのレイヤー一覧
コンテナイメージのレイヤー情報が出力されます。
この画面ではamazonlinuxのイメージを見ているだけなので1レイヤーのみですがDockerfileによるbuildを行うとレイヤー数が増えます。
②レイヤーダイジェスト値
コンテナのレイヤーダイジェスト値とコマンド情報が出力されます。
③イメージファイル情報
目玉の一つがこちらのイメージファイル情報です。 コンテナイメージは複数のレイヤーを重ねることによって、イメージの肥大化要因になり得るファイルが発生します。
実験的機能と明記されておりますが、余計なファイル情報の有無をスコアとサイズによって表記してくれます。
- イメージ自体のサイズ:
docker imagesで確認できるイメージサイズ - 余分なスペースサイズ:余分と思われるファイルサイズ数を表示
- コンテナイメージの効率スコア:コンテナイメージがどれだけ効率的な作りとなっているかを示すスコア
④イメージ内ディレクトリ構成
2つ目の目玉がこちらです。
コンテナイメージのディレクトリ構成を確認することが出来ます。
動きを見てみる(ファイル作成編)
以下のようなDockerfileを用意してみました。
単純に/tmp配下に1から10の連番を付与したファイルを作成します。
1 2 3 | FROM amazonlinux:latestRUN for i in {1..10} ; do touch /tmp/testfile-${i} ; done |
1 | docker build . -t amazonlinux:test |
このような結果になりました。
- 今回テストファイルを実行したコマンドがレイヤー一覧に追加
- ディレクトリ一覧の
/var配下に連番のtestfileが緑色で表示
ファイルが追加された時は緑色でハイライトされます。
動きを見てみる(ファイル削除編)
次に作成した連番ファイルであるtestfile-6 ~ testfile-10を削除します。
1 2 3 4 5 | FROM amazonlinux:latestRUN for i in {1..10} ; do touch /tmp/testfile-${i} ; doneRUN for i in {6..10} ; do rm -f /tmp/testfile-${i} ; done |
1 | docker build . -t amazonlinux:test |
このような結果になりました。
- ファイル作成編と同様に今回追加したレイヤーがレイヤー一覧に追加
- 削除された
testfile-6~testfile-10が赤色で表示
ファイルが削除された時は赤色でハイライトされます。
動きを見てみる(ファイル変更編)
作成済みのtestfile-1 ~ testfile-5を/配下にmodify-testfile-1 ~ modify-testfile-5へ変更します。
1 2 3 4 5 6 7 | FROM amazonlinux:latestRUN for i in {1..10} ; do touch /tmp/testfile-${i} ; doneRUN for i in {6..10} ; do rm -f /tmp/testfile-${i} ; doneRUN for i in {1..5} ; do mv /tmp/testfile-${i} modify-testfile-${i} ; done |
1 | docker build . -t amazonlinux:test |
このような結果になりました。
- 元々存在していた場所からファイルが移動(削除)されたため、
testfile-1~testfile-5が赤色で表示 - リネームされたファイルは新規追加ファイルとして緑色で表示
動きを見てみる(ファイル容量変更)
最後にddコマンドによって、modify-testfile-1のファイルをテストファイルに置き換えます。
1 2 3 4 5 6 7 8 9 10 11 | FROM amazonlinux:latestRUN for i in {1..10} ; do touch /tmp/testfile-${i} ; doneRUN for i in {6..10} ; do rm -f /tmp/testfile-${i} ; doneRUN for i in {1..5} ; do cp /tmp/testfile-${i} testfile-${i} ; doneRUN for i in {1..5} ; do mv /tmp/testfile-${i} /tmp/modify-testfile-${i} ; doneRUN dd if=/dev/zero of=/tmp/modify-testfile-1 bs=10M count=1 |
1 | docker build . -t amazonlinux:test |
この様な結果になりました。
- ファイルサイズが変更されたため、
modify-testfile-1が黄色で表示
便利な使い方
操作されたファイルのみ出力
Tabキーを押下することで右ペインを操作することができます。
この時に以下のキーを押下することで追加/変更/削除/未変更をフィルタリング出来ます。
| キーマップ | フィルタ |
|---|---|
| Ctrl + A | 追加ファイル |
| Ctrl + R | 削除ファイル |
| Ctrl + M | 変更ファイル |
| Ctrl + U | 未変更ファイル |
※Ctrl + Bはファイルパーミッション等を表示/非表示が可能です
dive buildを使ってdocker buildとdiveをシーケンシャルに起動
dive build -t <イメージ名> .を実行することでdocker buildを実行した後にdiveを開くことが出来ます。
※.部分はdocker buildコマンドのDockerfileパスの指定と同じなのでDockerfileが配置されているディレクトリ指定が可能です
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | % dive build -t amazonlinux:test .Building image...Sending build context to Docker daemon 18.19MBStep 1/8 : FROM amazonlinux:latest ---> dc34c260f454Step 2/8 : RUN for i in {1..10} ; do touch /tmp/testfile-${i} ; done ---> Using cache ---> b6bb763d53e5Step 3/8 : RUN for i in {6..10} ; do rm -f /tmp/testfile-${i} ; done ---> Using cache ---> 80fe5e4e730aStep 4/8 : RUN for i in {1..5} ; do cp /tmp/testfile-${i} testfile-${i} ; done ---> Using cache ---> 11339d266087Step 5/8 : RUN for i in {1..5} ; do mv /tmp/testfile-${i} /tmp/modify-testfile-${i} ; done ---> Using cache ---> eff7d1bd1402Step 6/8 : RUN dd if=/dev/zero of=/tmp/modify-testfile-1 bs=10M count=1 ---> Using cache ---> 38e8a0c4ce0bStep 7/8 : RUN dd if=/dev/zero of=/tmp/modify-testfile-2 bs=30M count=1 ---> Using cache ---> 31464c5894d0Step 8/8 : RUN dd if=/dev/zero of=/tmp/modify-testfile-3 bs=40M count=1 ---> Using cache ---> 27470ae7cd0fSuccessfully built 27470ae7cd0fSuccessfully tagged amazonlinux:testFetching image... (this can take a while with large images)Parsing image...Analyzing image...Building cache... |
環境変数を指定してCI環境に対応した分析を行う
CI=trueという環境変数を渡してdiveを実行すると、予め指定された余分なファイルサイズや分析結果を評価してリターンコードをで合否を出力します。
例えばCodeBuildのbuildspecにこのリターンコードを判定する文を追加すると面白いと思います。
合格パターン
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | % CI=true dive amazonlinux:test ; echo $? Using default CI configFetching image... (this can take a while with large images)Parsing image...Analyzing image... efficiency: 100.0000 % wastedBytes: 0 bytes (0 B) userWastedPercent: 0.0000 %Inefficient Files:Count Wasted Space File Path 2 0 B /tmp/testfile-5 2 0 B /tmp/testfile-4 2 0 B /tmp/testfile-3 2 0 B /tmp/testfile-2 2 0 B /tmp/testfile-1 2 0 B /tmp/testfile-9 2 0 B /tmp/testfile-8 2 0 B /tmp/testfile-7 2 0 B /tmp/testfile-6 2 0 B /tmp/testfile-10Results: PASS: highestUserWastedPercent SKIP: highestWastedBytes: rule disabled PASS: lowestEfficiencyResult:PASS [Total:3] [Passed:2] [Failed:0] [Warn:0] [Skipped:1]0 |
不合格パターン
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | % CI=true dive amazonlinux:test ; echo $? Using default CI configFetching image... (this can take a while with large images)Parsing image...Analyzing image... efficiency: 60.8036 % wastedBytes: 104857600 bytes (105 MB) userWastedPercent: 46.4845 %Inefficient Files:Count Wasted Space File Path 2 42 MB /tmp/modify-testfile-4 2 32 MB /tmp/modify-testfile-3 2 21 MB /tmp/modify-testfile-2 2 10 MB /tmp/modify-testfile-1 2 0 B /tmp/testfile-5 2 0 B /tmp/testfile-4 2 0 B /tmp/testfile-3 2 0 B /tmp/testfile-2 2 0 B /tmp/testfile-1 2 0 B /tmp/testfile-9 2 0 B /tmp/testfile-8 2 0 B /tmp/testfile-7 2 0 B /tmp/testfile-6 2 0 B /tmp/testfile-10Results: FAIL: highestUserWastedPercent: too many bytes wasted, relative to the user bytes added (%-user-wasted-bytes=0.4648447895112585 > threshold=0.1) SKIP: highestWastedBytes: rule disabled FAIL: lowestEfficiency: image efficiency is too low (efficiency=0.6080361515417759 < threshold=0.9)Result:FAIL [Total:3] [Passed:0] [Failed:2] [Warn:0] [Skipped:1]1 |
最後に
先日のecspressoに続きまして、今回はDiveというレイヤー分析ツールを触ってみました。
コンテナイメージの削減はコンテナ環境を運用する時に重要なポイントとなり、様々なコマンドを駆使すること形が多いと思います。
今回のツールでは手っ取り早く余分と考えられる部分を抽出出来るので使いやすいツールと思ってます。
少しでもコンテナイメージの削減を行いたい人に届くと嬉しいです。