Dockerファイル:【COPYとADD】どっち使う?


はじめに

  • Dockerファイルに記載するコマンド
  • COPYとADDの違いについて
  • docker buildでイメージ作成する処理のうちのひとつ

特徴比較

COPY

  • 機能
    • Dockerイメージ内にファイルを取り込む
    • コピー以外の処理は特に行わない
  • どこから?
    • dockerが動作している環境
      (docker buildしているところ)

ADD

  • 機能
    • Dockerイメージ内にファイルを取り込む
    • コピー元が「rootfs.tar.xz」のようなtarボールから抽出できる(COPYにない機能)
  • どこから?
    • dockerが動作している環境
      (docker buildしているところ)
    • URL先の環境(COPYにない機能)
  • 補足(下記引用の通り)
    • ローカルの.gzipか.bzip2か.xzだったら展開できる
      (ディレクトリとして展開)
    • コピー元がURLの場合は展開しない
      ※引用文の<src>とはADDの参照元ファイル

If <src> is a local tar archive in a recognized compression format (identity, gzip, bzip2 or xz) then it is unpacked as a directory.

Resources from remote URLs are not decompressed.

Dockerfile reference | Docker Documentation

ADDを利用するかどうか

COPY利用が基本

  • 一般的にはCOPYを推奨(下記引用の通り)
    • ADDとCOPYは似ている
    • COPYの方が分かりやすい
    • COPYはコンテナ(イメージ)にコピーするだけ
    • ADDはいろんな特徴があってすぐには理解できない

Although ADD and COPY are functionally similar, generally speaking, is preferred COPY. That’s because it’s more transparent than ADD.COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that ADD are not immediately obvious.

Best practices for writing Dockerfiles | Docker Documentation

ADD使う場合

  • tarボールを展開するならADD使ってよい(下記引用の通り)
    • ローカルにあるファイルをイメージに入れるとき
    • 例えば「/(ルートディレクトリ)」にある「rootfs.tar.xz」のようなファイル

Consequently, the best use for ADD is local tar file auto-extraction into the image, as rootfs.tar.xz in /.

Best practices for writing Dockerfiles | Docker Documentation

ADDが推奨されない場合

よくない例

ADD https://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all
  • 避けた方がいい使い方がある(引用の通り)
    • この例はイメージサイズが考慮されていない点でよくない
    • 不要なデータ(/usr/src/things/にコピーしたbig.tar.xz)がイメージに含まれる
    • curlやwgetを利用すると必要なくなった時点でファイルを削除するので代替手順になりうる

Because image size matters, using ADD to fetch packages from remote URLs is strongly discouraged; you should use curl or wget instead. That way you can delete the files you no longer need after they’ve been extracted and you don’t have to add another layer in your image. For example, you should avoid doing things like:

Best practices for writing Dockerfiles | Docker Documentation

代替手順

RUN mkdir -p /usr/src/things \
    && curl -SL https://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all
  • ADDを利用しないで実装できる(下記引用の通り)

And instead, do something like:

Best practices for writing Dockerfiles | Docker Documentation

COPYの注意点

よくない例

COPY requirements.txt /tmp/
COPY . /tmp/
RUN pip install --requirement /tmp/requirements.txt
  • COPYは一度に実行しない方がいい(下記引用の通り)
    • 例えば、RUNでビルドコンテキストではないファイルを使う場合
    • ビルドキャッシュは都度無効にされるため
  • 参考

If you have multiple steps Dockerfile that use different files from your context, COPY them individually, rather than all at once. This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.

Best practices for writing Dockerfiles | Docker Documentation

よい例

COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/
  • 下段のCOPYはRUNにより無効されない(下記引用の通り)

Results in fewer cache invalidations for the RUN step, than if you put the [COPY . /tmp/] before it.

Best practices for writing Dockerfiles | Docker Documentation

補足

英文書き直し

Although ADD and COPY are functionally similar, generally speaking, is preferred COPY. That’s because it’s more transparent than ADD.COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that ADD are not immediately obvious. Consequently, the best use for ADD is local tar file auto-extraction into the image, as rootfs.tar.xz in /.

If you have multiple steps Dockerfile that use different files from your context, COPY them individually, rather than all at once. This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.

Results in fewer cache invalidations for the RUN step, than if you put the [COPY . /tmp/] before it.

Because image size matters, using ADD to fetch packages from remote URLs is strongly discouraged; you should use curl or wget instead. That way you can delete the files you no longer need after they’ve been extracted and you don’t have to add another layer in your image. For example, you should avoid doing things like:

And instead, do something like:

  • 参照したドキュメントはキーワードが文末に固まって表示された(2022/2現在)
    • そのままでは意味が理解できない
    • 適切な位置にキーワードを再配置

リファレンス


Posted by futa