Dockerfileの「COPY」コマンドと「ADD」コマンドの違いは何ですか?


2196

DockerfileのコマンドCOPYADDコマンドの違いは何ですか?また、いつどちらを使用するのですか?

COPY <src> <dest>

COPY命令は<src>、パスからコンテナーのファイルシステムに新しいファイルをコピーして追加します<dest>

ADD <src> <dest>

ADD命令は、新しいファイルをからコピー<src>し、パスにあるコンテナーのファイルシステムに追加します<dest>


11
ベストプラクティスを参照してください。docs.docker.com/engine/userguide/eng-image/...
EricSonaron

9
2018年6月の参照では、ADDはイメージ(つまり、静的ファイル)に追加され、COPYはコンテナー(つまり、イメージのランタイムインスタンス)に追加されると述べています。確かにこれは、イメージがDockerで実行されるたびにCOPYが実行されることを意味しますか、またはこれは単に一貫性のない用語の場合でしょうか?
Chris Robinson

14
それは一貫性のない用語だと思います
ダニエルスティーブンス

6
@ChrisRobinsonではCOPY、コンテンツを取得するために必ずしも元のコンテキストにアクセスできるとは限らないため、実行するたびにを実行することは不可能です。
ケンウィリアムズ

回答:


2169

これらの動作の詳細な説明については、ADDおよびCOPYドキュメントを確認する必要がありますが、簡単に言うと、主な違いは次のことADDだけではありませんCOPY

  • ADD<src>URLにすることができます
  • 以下のコメントを参照して、ADD ドキュメントは次のように述べています:

    が、認識された圧縮形式(identity、gzip、bzip2、またはxz)のローカルtarアーカイブである場合は、ディレクトリとして解凍されます。リモートURLからのリソースは解凍されません。

Dockerfileを作成するためベストプラクティスCOPYADDは、マジックが不要な場所での使用を推奨していることに注意してください。そうしないと、(この答えを調べる必要があったため)いつかkeep_this_archive_intact.tar.gzコンテナにコピーするつもりで驚かれる可能性がありますが、その代わりにコンテンツをファイルシステムにスプレーします。


65
何かを明確にしたかった:.tar.gzへのURLでADDを使用すると、アーカイブがファイルシステムに抽出されない(確認のために今すぐダブルチェックして確認済み)
Cecile

42
これは重要な情報であり、Dockerfileの公式リファレンスでこの方法の違いが明確にされていないのは犯罪です。
Cheeso

1
これが画像間で異なるかどうかはわかりません。zipファイルにbusyboxイメージとADDを使用しました。解凍せずに単に宛先ディレクトリに現れただけです。抽出はtarballに対してのみ行われると思いますが、今のところ確認していません。
Santosh Kumar Arjunan

4
@SantoshKumarArjunan:Dockerのドキュメントでは、ADDと自動tar抽出について次のように述べられています: 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. Docker ADD
hmacias

1
COPYは--from = <name | index>を許可しますが、ADDに対する同じサポートが見つかりません
Brandon

474

COPY です

'ADD'と同じですが、tarおよびリモートURL処理はありません。

ソースコードから直接参照。


15
これは正しく表示されますか?存在しないディレクトリADD作成されます。それは何らかの形でこの全体のスレッドで推奨されたがそう、それは持っている利点を超えるをCOPYあなたが実行する必要はありませんのでmkdir、いくつかの入力をして保存
イーライ

3
COPYもそれを行います@eli
bhordupur

これまでの最高の説明。なぜそれは受け入れられない答えですか?
xdevx32

141

その点に関するいくつかの公式ドキュメントがあります:Dockerfilesを作成するためのベストプラクティス

画像サイズが重要であるためADD、リモートURLからパッケージをフェッチするためにを使用することは強くお勧めしません。curlまたはwget代わりに使用する必要があります。これにより、抽出後に不要になったファイルを削除でき、画像に別のレイヤーを追加する必要がなくなります。

RUN mkdir -p /usr/src/things \
  && curl -SL http://example.com/big.tar.gz \
    | tar -xJC /usr/src/things \
  && make -C /usr/src/things all

必要としないその他のアイテム(ファイル、ディレクトリ)の場合 ADDのtar自動抽出機能を、常にを使用する必要がありますCOPY



18
DockerはCOPY、より透過的であるため、を好むと述べています。ドッカーファイルのベストプラクティス:(2014年12月15日) Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. 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 that are not immediately obvious.
schemar

115

Docker docsから:

追加またはコピー

ADDとCOPYは機能的に類似していますが、一般的に言えば、COPYが推奨されます。これは、ADDよりも透過的であるためです。COPYは、ローカルファイルのコンテナーへの基本的なコピーのみをサポートしていますが、ADDには、すぐには明らかにならない機能(ローカルのみのtar抽出やリモートURLサポートなど)があります。したがって、ADD rootfs.tar.xz /のように、ADDの最適な使用法は、イメージへのローカルtarファイルの自動抽出です。

詳細:Dockerfileを作成するためのベストプラクティス


46

xx.tar.gzを /usr/localコンテナー内場合は、それを解凍して、な圧縮パッケージを削除します。

コピーの場合:

COPY resources/jdk-7u79-linux-x64.tar.gz /tmp/
RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local
RUN rm /tmp/jdk-7u79-linux-x64.tar.gz

追加の場合:

ADD resources/jdk-7u79-linux-x64.tar.gz /usr/local/

ADDはローカルのみのtar抽出をサポートします。その上、COPYは3つのレイヤーを使用しますが、ADDは1つのレイヤーのみを使用します。


3
2層だけではない理由は何ですか?RUN tar -zxvf /tmp/jdk-7u79-linux-x64.tar.gz -C /usr/local && rm /tmp/jdk-7u79-linux-x64.tar.gz
スティーブンC

25

COPY ホストからイメージにファイル/ディレクトリをコピーします。

ADD ホストからイメージにファイル/ディレクトリをコピーしますが、リモートURLのフェッチ、TARファイルの抽出などもできます...

使用する COPYファイルやディレクトリをビルドコンテキストに単にコピーためにします。

ADDリモートリソースのダウンロード、TARファイルの抽出などに使用します。


5
私のような
初心者の

17

Docker docsから:https : //docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

「ADDとCOPYは機能的に類似していますが、一般的に言えばCOPYが推奨されます。これは、ADDよりも透過的であるためです。COPYは、ローカルファイルのコンテナーへの基本的なコピーのみをサポートしますが、ADDにはいくつかの機能(ローカルのみのtar抽出やリモートURLのサポート)はすぐにはわかりません。そのため、ADDの最適な用途は、ADD rootfs.tar.xz /のように、ローカルtarファイルをイメージに自動抽出することです。

コンテキストから異なるファイルを使用する複数のDockerfileステップがある場合は、一度にすべてではなく、それらを個別にコピーします。これにより、特に必要なファイルが変更された場合にのみ、各ステップのビルドキャッシュが無効化されます(ステップを強制的に再実行します)。

例えば:

 COPY requirements.txt /tmp/
 RUN pip install --requirement /tmp/requirements.txt
 COPY . /tmp/

COPYを配置する場合よりも、RUNステップのキャッシュ無効化が少なくなります。その前の/ tmp /。

画像サイズが重要であるため、リモートURLからパッケージをフェッチするためにADDを使用することは強くお勧めしません。代わりにcurlまたはwgetを使用してください。これにより、抽出後に不要になったファイルを削除でき、画像にレイヤーを追加する必要がなくなります。たとえば、次のようなことは避けてください。

 ADD http://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

そして代わりに、次のようなことをしてください:

 RUN mkdir -p /usr/src/things \
     && curl -SL htt,p://example.com/big.tar.xz \
     | tar -xJC /usr/src/things \
     && make -C /usr/src/things all

ADDのtar自動抽出機能を必要としない他のアイテム(ファイル、ディレクトリ)については、常にCOPYを使用する必要があります。


7

ソース:https : //nickjanetakis.com/blog/docker-tip-2-the-difference-between-copy-and-add-in-a-dockerile

COPYとADDはどちらも、同様の目的を果たすDockerfile命令です。特定の場所からDockerイメージにファイルをコピーできます。

COPYはsrcと宛先を受け取ります。ホスト(Dockerイメージを構築しているマシン)からローカルファイルまたはディレクトリをDockerイメージ自体にコピーすることのみが可能です。

ADDでもそれが可能ですが、他の2つのソースもサポートしています。まず、ローカルファイル/ディレクトリの代わりにURLを使用できます。次に、ソースから直接tarファイルを宛先に抽出できます

ADDの有効な使用例は、ローカルtarファイルをDockerイメージの特定のディレクトリに抽出する場合です。

ローカルファイルをDockerイメージにコピーする場合は、明示的であるため、常にCOPYを使用します。


7

Dockerfileを作成する場合、それにファイル/ディレクトリをコピーするために使用できる2つのコマンドがありますADDCOPY。それらの機能の範囲にはわずかな違いがありますが、基本的に同じタスクを実行します。

では、なぜ2つのコマンドがあり、どちらを使用するかをどのようにして知るのでしょうか。

ドッカーADDコマンド

ADDコマンドがよりも古いことに注意してみましょうCOPY。Dockerプラットフォームのリリース以来、このADD命令はコマンドリストの一部になっています。

このコマンドは、ファイル/ディレクトリを指定されたコンテナーのファイルシステムにコピーします。

ADDコマンドの基本的な構文は次のとおりです。

ADD <src> … <dest>

これには、コピーするソース(<src>)の後に、保存先()が続きます<dest>。ソースがディレクトリの場合、ADD中のすべてをコピーします(ファイルシステムメタデータを含む)。

たとえば、ファイルがローカルで利用可能であり、それをイメージのディレクトリに追加する場合は、次のように入力します。

ADD /source/file/path  /destination/path

ADDURLからファイルをコピーすることもできます。外部ファイルをダウンロードして、目的の宛先にコピーできます。例えば:

ADD http://source.file/url  /destination/path

追加機能として、圧縮ファイルがコピーされ、指定された宛先のコンテンツが自動的に抽出されます。この機能は、ローカルに保存された圧縮ファイル/ディレクトリにのみ適用されます。

ADD source.file.tar.gz /temp

URLから圧縮ファイル/ディレクトリをダウンロードして抽出することはできないことに注意してください。コマンドは、ローカルファイルシステムにコピーするときに外部パッケージを解凍しません。

ドッカーCOPYコマンド

いくつかの機能上の問題により、Dockerはコンテンツを複製するための追加コマンドを導入する必要がありました– COPY

密接に関連するADDコマンドとは異なり、COPY割り当てられた機能は1つだけです。その役割は、指定された場所にあるファイル/ディレクトリを既存の形式で複製することです。つまり、圧縮ファイルの抽出は処理されず、そのままコピーされます。

この命令は、ローカルに保存されたファイルに対してのみ使用できます。したがって、URLとともに使用して外部ファイルをコンテナーにコピーすることはできません。

を使用するには COPY命令には、基本的なコマンド形式に従います。

次のように、ソースとコマンドでコンテンツを抽出する場所を入力します。

COPY <src> … <dest> 

例えば:

COPY /source/file/path  /destination/path 

使用するコマンド(ベストプラクティス)

COPYコマンドが導入された状況を考慮すると、維持ADDが必要であったことは明らかです。Dockerは、Dockerfileを作成するためのベストプラクティスを概説する公式ドキュメントをリリースしましたADD

Dockerの公式ドキュメントには、よりわかりやすいCOPYため、常に頼りになる説明であると記載されていADDます。

ローカルビルドコンテキストからコンテナーにコピーする必要がある場合は、そのまま使用しCOPYます。

Dockerチームは、を使用ADDしてURLからパッケージをダウンロードおよびコピーすることも強くお勧めしません。代わりに、RUNコマンド内でwgetまたはcurlを使用する方がより安全で効率的です。そうすることで、追加の画像レイヤーの作成を避け、スペースを節約できます。


4

重要な注意点

COPYdockerイメージのjavaパッケージを解凍しなければなりませんでした。ADDを使用して作成されたDockerイメージのサイズを比較すると、COPYを使用して作成されたものよりも180MB大きくなりました。tar-xzf * .tar.gzおよびrm * .tar.gz

つまり、ADDはtarファイルを削除しますが、どこかに保持されます。そして、そのイメージを大きくします!!


これは最新バージョンのDockerにも当てはまりますか?
Navin、

3

Docker 17.05 COPYマルチステージビルドで--fromフラグと共に使用されるため、以前のビルドステージから現在のビルドステージにアーティファクトをコピーします。

ドキュメントから

オプションで、COPYは--from=<name|index>、ユーザーが送信したビルドコンテキストの代わりに使用される(FROM .. ASで作成された)前のビルドステージにソースの場所を設定するために使用できるフラグを受け入れます。


0
docker build -t {image name} -v {host directory}:{temp build directory} .

これは、ファイルをイメージにコピーするもう1つの方法です。-vオプションは、ビルドプロセス中に使用したボリュームを一時的に作成します。

ビルドのみのホストディレクトリをマウントするため、これは他のボリュームとは異なります。ファイルは、標準のcpコマンドを使用してコピーできます。

また、curlやwgetと同様に、コマンドスタック(単一のコンテナーで実行)で実行でき、イメージサイズを乗算しません。ADDおよびCOPYは、スタンドアロンコンテナーで実行され、追加のコンテナーで実行されるそれらのファイルに対する後続のコマンドがイメージサイズを乗算するため、スタックできません。

オプションを設定すると、次のようになります。

-v /opt/mysql-staging:/tvol

以下は1つのコンテナーで実行されます。

RUN cp -r /tvol/mysql-5.7.15-linux-glibc2.5-x86_64 /u1 && \
    mv /u1/mysql-5.7.15-linux-glibc2.5-x86_64 /u1/mysql && \

    mkdir /u1/mysql/mysql-files && \
    mkdir /u1/mysql/innodb && \
    mkdir /u1/mysql/innodb/libdata && \
    mkdir /u1/mysql/innodb/innologs && \
    mkdir /u1/mysql/tmp && \

    chmod 750 /u1/mysql/mysql-files && \
    chown -R mysql /u1/mysql && \
    chgrp -R mysql /u1/mysql

1
そのオプションが表示されているドッカーのバージョンは何ですか?それは文書化されておらず、私の1.12.1クライアントでは動作しません。
BMitch 2016

2
実際、この機能はまだメインリリースに含まれておらず、このテーマについてはまだ多くの議論が行われているため、しばらく前に期待するべきではありません...詳細については、バグレポートを参照してください:github.com/ docker / docker / issues / 14080
jwatkins 2016

1
ええ、そのようなオプションはありません(最新バージョン17.06でチェックされています)。この答えは誤解を招くものです。unknown shorthand flag: 'v' in -v
カービー

実際に誤解を招くコメント
Guido van Steen

Dockerボリュームは答えでここでは何もしませんでした。直接の質問に答えてください:)、それは簡単に反対票の答えです。
マジッドアリカーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.