畑田です。
最近チーム内での開発でDockerfileを書くことがしばしばあるのですが、いくつ書きになる点があったので整理しました。
その中でもADD
とCOPY
の違いとともに**COPY
における注意点**をまとめておきます。
DockerfileのADD
とCOPY
について
ADD
とCOPY
は機能が似ていますが、COPY
が単にlocalのファイルをcontainerにコピーするだけなのに対して、ADD
はtarファイルの展開やremote URLからのデータの取得をサポートしています。
したがって、localファイルのコピーを意図しているときにはより限定的な意味のCOPY
を用いることがdockerによって推奨されています。
さらに、ADD
によってremote URLを用いてリソースを取得することは非推奨とされており、curl
やwget
をRUN
コマンドによって実行することが推奨されます。
このため、ADDコマンドはtar展開などを含んだcontainerへのリソース追加に適用することが推奨されていると考えられます。
DockerfileのCOPY
における注意点
上の項目でも推奨しているCOPY
について、directoryをコピーするときに注意する必要があります。
まず、以下のようにファイルをコピーするときにはなんら問題は生じません。
COPY ./package*.json ./
しかし、次のようにdirectory自体をコピーしようとするときに問題は生じます。
COPY ./src/ ./
このように書いてしまうと、host machineの./src/
の中身がcontainer machineの./
のなかに展開されてコピーされてしまいます。(イメージはJavaScriptの[...data]
です。違うか。)
つまり、container machineの./
が空であれば、container machineの./
はhost machineの./src/
と全く同じものになるし、もともと中身が入っていればmergeされてしまうということです。
展開せずにcontainer machineの./
の下に./src
としてコピーしたい場合は以下のように記述してください。
COPY ./src/ ./src/
この仕様に若干の違和感があるのは、Linux系共通コマンドである以下のものと仕様が異なるからだと思います。
$ cp -r DIRECTORY_NAME DESTINATION