web-dev-qa-db-ja.com

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

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

COPY <src> <dest>

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

ADD <src> <dest>

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

1806
Steve

あなたは ADDCOPY のドキュメントでそれらの振る舞いの徹底的な説明をチェックするべきですが、一言で言えばADDCOPY以上のことができるということです:

  • ADD<src>をURLにすることを可能にします
  • ADD<src>パラメータが認識された圧縮形式のアーカイブである場合、それは解凍されます

Dockerfilesを書くためのベストプラクティス は、COPYの魔法が必要ではない場合にADDを使うことを示唆していることに注意してください。さもなければあなたは(あなたがこの答えを調べなければならなかったので)あなたがkeep_this_archive_intact.tar.gzをあなたのコンテナにコピーしようとするときいつか驚くかもしれませんが、代わりにあなたはあなたのファイルシステムに内容をスプレーします。

1804
icecrime

COPY

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

直接ソースコードから

375
caike

その点に関する公式の文書がいくつかあります: 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を使うべきです。

125
Victor Laskin

Dockerのドキュメントから:

追加またはコピー

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

More: Dockerfilesを書くためのベストプラクティス

102
eddd

Xx.tar.gzをコンテナ内の/usr/localに追加する場合は、それを解凍してから、不要な圧縮パッケージを削除します。

COPYの場合:

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つのレイヤーしか使いません。

35
BertLi

Dockerのドキュメントから: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#add-or-copy

「ADDとCOPYは機能的には似ていますが、一般的に言って、COPYが好ましいのです。これは、ADDよりも透過的であるためです。そのため、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を使用するべきです。」

12
jhpg

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

ADDはあなたのホストからあなたのイメージにファイル/ディレクトリをコピーしますが、リモートURLの取得、TARファイルの抽出などもできます。

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

ADDを使ってリモートリソースをダウンロードしたり、TARファイルを展開したりします。

6
JSON C11

_コピー_

これにより、1つ以上のローカルファイルまたはフォルダがDockerイメージ内の保存先にコピーされます。

COPY < src> < dest >

COPY ["< source >",... "< destination >"] 

(この形式は空白を含むパスに必要です)

COPYを使用するDockerfileの例これはRubyアプリケーションのDockerfileでCOPYを使用する方法です。

FROM Ruby:2.5.1
WORKDIR /usr/src/app
COPY Gemfile Gemfile.lock ./
RUN bundle install
COPY . .
CMD ["./your-daemon-or-script.rb"]

これは、FROMを使用して定義された親イメージRuby:2.5.1から始めて、レイヤーでイメージを構築します。

Docker命令のWORKDIRは、それに続くCOPYまたはADD命令の作業ディレクトリを定義します。

Gemfilesの後にRUN bundle installをコピーすることで、インストールされたRuby Gemsを使ってイメージレイヤーが作成されます。最後の2つのDocker命令は、アプリのファイルをイメージにコピーし、CMDを使用してデフォルトのコマンドを設定します。

つまり、アプリのファイルを変更した場合は、キャッシュされた親レイヤーと中間レイヤーを使用してDockerイメージを再構築できます。これは、すべてをゼロから構築するよりもはるかに効率的です。

_追加_

この命令はCOPYと似た構文をしています。

ADD < src> < dest >

ADD ["< source >",... "< destination >"] (this form is required for paths containing whitespace)

ローカルファイルやディレクトリをDockerイメージ内のコピー先にコピーするだけでなく、いくつかの追加機能があります。

<source>が認識された圧縮形式のローカルのtarアーカイブである場合、それはDockerイメージへのディレクトリとして自動的に解凍されます。例えば、次のとおりです。ADD rootfs.tar.xz /

<source>がURLの場合は、ファイルをダウンロードしてDockerイメージ内の保存先にコピーします。しかし、Dockerはこの目的のためにADDを使用することを勧めません。

URLからコピーするためのDockerfileのベストプラクティス

Dockerは、ADDを使用してURLからコピーするのは効率的ではないことが多く、必要なリモートファイルを含めるために他の方法を使用することをお勧めします。

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

たとえば、次のようなことは避けてください。

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 http://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all

ADDのtar自動抽出機能を必要としない他の項目(ファイル、ディレクトリ)については、常にCOPYを使うべきです。

4
Prakash

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

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

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

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

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

ローカルファイルをDockerイメージにコピーインする場合は、明示的なので常にCOPYを使用してください。

3
Shagun Pruthi

重要な注意点

私は自分のdockerイメージの中でJavaパッケージをCOPYそしてuntarしなければなりませんでした。 ADDを使用して作成されたdockerイメージのサイズを、COPYを使用して作成されたものと比べて180MB大きくなっています。

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

2
Avi Veltz

Docker 17.05のCOPYmulti-stage builds--fromフラグと一緒に使用されるため、前のビルドステージから現在のビルドステージにアーティファクトをコピーします。

ドキュメント から

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

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

これはファイルを画像にコピーするもう一つの方法です。 -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
0
Dennis Payne