Dockerファイル:【COPYとADD】どっち使う?
はじめに
- Dockerファイルに記載するコマンド
- COPYとADDの違いについて
- docker buildでイメージ作成する処理のうちのひとつ
特徴比較
COPY
- 機能
- Dockerイメージ内にファイルを取り込む
- コピー以外の処理は特に行わない
- どこから?
- dockerが動作している環境
(docker buildしているところ)
- dockerが動作している環境
ADD
- 機能
- Dockerイメージ内にファイルを取り込む
- コピー元が「rootfs.tar.xz」のようなtarボールから抽出できる(COPYにない機能)
- どこから?
- dockerが動作している環境
(docker buildしているところ)
- URL先の環境(COPYにない機能)
- dockerが動作している環境
- 補足(下記引用の通り)
- ローカルの.gzipか.bzip2か.xzだったら展開できる
(ディレクトリとして展開)
- コピー元がURLの場合は展開しない
※引用文の<src>とはADDの参照元ファイル
- ローカルの.gzipか.bzip2か.xzだったら展開できる
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でビルドコンテキストではないファイルを使う場合
- ビルドキャッシュは都度無効にされるため
- 参考
- ビルドコンテキスト
- Docker:【ビルドコンテキスト】とは?
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現在)
- そのままでは意味が理解できない
- 適切な位置にキーワードを再配置
リファレンス
- Best practices for writing Dockerfiles | Docker Documentation
- ADD or COPY
- Dockerfile reference | Docker Documentation
- ADDの説明
