docker

リファレンス

オフィシャル

Dockerfile の見直す時に参考にする場所

Dockerfile のベストプラクティス その 1 ) 下記以外にもあるが私が忘れやすいポイントだけ

  • .dockerignore ファイルを使う
  • レイヤの数を最小に
  • 複数行の引数 <= 引数はアルファベット順に
  • 構築キャッシュ <= docker build で –no-cache=true とすると既存キャッシュを使わない
  • CMD <= 常に CMD [“executable”, “param1”, “param2”…] のような形式で使うべきです。
  • WORKDIR <= 明確さと信頼性のため、常に WORKDIR からの絶対パスを使うべきです。
  • Distroless が使えないか検討する

その 2

  • LABEL <= ロジェクト内でのイメージ管理をしやすくしたり、ライセンス情報の記録や自動化の助けとするなど、さまざまな目的があります。

レイヤー削減の考え方

Dockerfile の layer を減らす時は、単純に RUNCOPY を結合すればよい、という話ではない。 layer 数を減らすと見た目はきれいになるが、巨大な layer にまとまると push/pull 時の差分再利用や、docker history での原因調査が悪くなることがある。

特に日常利用の CLI image のように、apt package、language runtime、npm global tool、クラウド CLI などを大量に含む image では、layer 数と image size は別の問題として扱う。

忘れやすい実務上のポイント:

  • COPY --chmod=0755 file /path/file で済む場合は、COPY 後の RUN chmod layer を作らない。
  • 一時ファイルや cache は、生成した同じ RUN の末尾で消す。後続の RUN rm -rf ... では過去 layer の bytes は消えない。
  • WORKDIR /tmp/fooRUN ...WORKDIR /RUN rm -rf /tmp/foo のような空に近い cleanup layer は作らず、mktemp -dtrap で同じ RUN に閉じ込める。
  • multi-stage build では、builder stage から runtime に必要な成果物だけを /out などへ集めて final stage にコピーする。toolchain や package manager の cache を final に持ち込まない。
  • 複数の builder stage から成果物を final stage へ個別に COPY している場合は、FROM scratch AS artifacts のような集約 stage に一度まとめ、final stage では COPY --from=artifacts / / の 1 layer にする選択肢がある。
  • 同じ CLI を apt、aqua、手動 download など複数経路で入れない。PATH 上で shadow される実体は、容量と layer の両方で無駄になりやすい。
  • FROM scratch に rootfs を丸ごと COPY する squash 風の構成は layer 数を大きく減らせるが、差分配布と調査性が悪くなるので最後の手段と考える。

実例: cli-tool-docker のイメージサイズ調査

参考

マルチステージビルドの利用
現実に効果的な Dockerfile を書くためには、
いつもながらトリッキーなシェルのテクニックや、
レイヤーができる限り小さくなるようなロジックを考えたりすることが必要でした。
つまり各レイヤーは、それ以前のレイヤーから受け継ぐべき生成物のみを持ち、
他のものは一切持たないようにすることが必要であったわけです。
本来 2 つあるRUNコマンドを Bash の&&オペレーターによって連結しています。
これを行うことで、イメージ内に不要なレイヤーが生成されることを防いでいます。
ただこれでは間違いを起こしやすく、保守もやりづらくなります。

保守がやりづらくなる、という認識は docker にもあるようだ。