Dockerの性能を最大限に引き出すためには、Dockerfileの記述を最適化し、ビルド後のイメージの容量をできるだけ小さくすることが大切です。さまざまなテクニックがDockerfileのベストプラクティス集などにまとめられるなど、多くのエンジニアの関心を集めているこの最適化問題について、エンジニアのヴァムシ・アトゥーリさんが「適切にchmodを利用することでコンテナイメージの容量を35%削減した」というブログ記事を投稿し、エンジニアが集うニュースサイト「Hacker News」で話題になっています。

`COPY --chmod` reduced the size of my container image by 35%

https://blog.vamc19.dev/posts/dockerfile-copy-chmod/

`COPY -chmod` reduced the size of my container image by 35% | Hacker News

https://news.ycombinator.com/item?id=30808945

事の発端は下記のDockerfileでした。このDockerfileはバイナリをダウンロードしてきて実行するだけの内容となっています。



アトゥーリさんはビルド後のイメージの容量について、ベースのubuntuが70MB&ダウンロードしてくるバイナリが80MBだったため、その他のパッケージを合わせても160MBくらいだと予想していました。しかし、実際にビルドしてみるとその容量が267MBにもなっていたとのこと。

レイヤーごとの容量を確認してみると、COPYレイヤーが87.7MBとなっていますが、これはバイナリと同じ容量とのことで問題ありません。一方で、RUNレイヤーの容量は94.4MBと異常に大きいものとなってしまっていました。



アトゥーリさんがRUNの内容の中からchmodを抜いてビルドし直してみると、RUNレイヤーの容量が6.7MBにまで減少。アトゥーリさんはchmodだけではファイルの変更はメタデータのみとなり、中身を書き換えないのでコピーされないと考えていたそうですが、オーバーレイファイルシステム(ユニオンファイルシステム)のドキュメントを確認してみると、「書き込み権限付きでファイルを開いたり、メタデータを変更すると上のレイヤーにファイルがコピーされる」と記載されていたとのこと。

アトゥーリさんは解決策として、COPY後にRUNでchmodを実行する代わりに、COPY時に「--chmod」オプションを利用することで容量を肥大化させずに権限を変更可能だと述べています。この「--chmod」オプションはBuildKitやPodmanで利用可能とのこと。

このブログ投稿を受け、Hacker Newsでは多数のエンジニアがDockerイメージを軽量化する方法についてコメントを残しています。記事作成時点でのトップコメントは「手動で試行錯誤するよりも自動でイメージを解析して軽量化してくれるツールのDockerSlimを使うのが良い」といういかにもエンジニアらしいものとなっていました。

また別のコメントでは「今回の本当の問題はマルチステージビルドの利用方法が間違っていることで、COPY --chmodは正しい解決策ではない」という指摘がなされており、アトゥーリさんはこの指摘に同意しつつもCOPY --chmodはマルチステージビルド以外の場合でも適用できる一般的な解決策だと述べています。