見出し画像

DockerfileのCOPYに惑わされたトホホな件

畑田です。

最近チーム内での開発で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

公式ドキュメントにサンプルも置かれていたのに、いい加減に書いていたので痛い目を見た経験から書かせてもらいました。
皆さんもdockerで良い開発体験をお試しください♪