Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
49
Help us understand the problem. What is going on with this article?
@momotaro98

DockerfileにてなぜADDよりCOPYが望ましいのか

はじめに

Docker公式のBest practices for writing Dockerfiles
ADDよりもCOPYが望ましい(ADDは使わない方が良い)との記述があるのを見つけたのでその理由を確認してみました。

TL;DR

理由は以下の2つに分けることができます。

① Imageサイズの観点
② セキュリティの観点

そもそもCOPYとADDはどう違うのか

こちらの記事にて端的にまとめられていたので日本語訳してしまいます。

COPY - 明示的なコピー元とコピー先のファイルまたはディレクトリを指定して、ローカルファイルを再帰的にコピーします。 COPYでは、場所を宣言する必要があります。

ADD - ローカルファイルを再帰的にコピーし、存在しない場合は暗黙的にコピー先ディレクトリを作成し、アーカイブをコピー元としてローカルURLまたはリモートURLとして受け入れます。アーカイブはそれぞれコピー先ディレクトリに展開またはダウンロードされます。

COPYはソース側のマシンにあるものをImageへコピーするだけというシンプルな機能であるのに対し、ADDは対象が圧縮ファイルであればそれを展開してImageへ移し、リモート上のリソースも引っ張ってくる機能がついています。このCOPYに付与されたADDの機能自体が望ましくない原因になっています。

Imageサイズの観点

上記の公式ドキュメントに記載の内容です。

ADDを使ってしまっているアンチパターンが以下になります。

ダメな例
FROM alpine:3.4
RUN apk --update add curl

ADD https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/Python-3.7.3.tar.xz -C /usr/src/things

これの何がいけないかというと、ADD https://...tar.xz /usr/src/thingsの記述により結果的に不要なダウンロードされたディレクトリを持つImageレイヤーができてしまっている点です。

そうではなく、このようにしましょうということです。

改良
FROM alpine:3.4
RUN apk --update add curl

RUN mkdir -p /usr/src/things \
    && curl -SL https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tar.xz \
    | tar -xJC /usr/src/things

それぞれをビルドしてdocker imagesdocker historyで比較してみましょう。

ダメな例
$ docker images ng-sample
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ng-sample           latest              6f486d575040        15 minutes ago      103MB

$ docker history ng-sample
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
6f486d575040        15 minutes ago      /bin/sh -c tar -xJf /usr/src/things/Python-3…   79.3MB
7640da035c96        15 minutes ago      /bin/sh -c #(nop) ADD da2574b8e3fb62fc8442c4…   17.1MB
15a01069edfd        26 minutes ago      /bin/sh -c apk --update add curl                2.19MB
b7c5ffe56db7        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:bcde2f5c6cea41907…   4.82MB
改良
$ docker images ok-sample
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ok-sample           latest              c88218b0c0cf        28 minutes ago      86.3MB

$ docker history ok-sample
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
c88218b0c0cf        28 minutes ago      /bin/sh -c mkdir -p /usr/src/things     && c…   79.3MB
15a01069edfd        29 minutes ago      /bin/sh -c apk --update add curl                2.19MB
b7c5ffe56db7        3 months ago        /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           3 months ago        /bin/sh -c #(nop) ADD file:bcde2f5c6cea41907…   4.82MB

ダメな方ではADDで追加された圧縮ファイルを持ったレイヤー分サイズが大きくなってしまっています。改良版ではcurlした圧縮ファイルをパイプでtarへつなげているのでImageには残りません。

セキュリティの観点

こちらの記事の内容の紹介になります。

上記のADDの機能を利用者が知らずに使っている場合、ADDはセキュリティのリスクが生じてしまいます。

  • リモート上のリソースを自動で取りに行くのでダウンロード中、中間者攻撃の対象となりえる
  • 圧縮ファイルを自動で展開するので、ZIP爆弾ZIP SLIP脆弱性攻撃の対象となりえる

ここで注意するべきは、上記のセキュリティリスクはCOPYを使っている場合でも起こりえます。ただ、COPYを使っていれば、

  • 明示的にリモートリソースからダウンロード(wget, curlなど)をする
  • 圧縮ファイルを展開(tarなど)する

ので対象リソースが安全かを検証する仕組みを組み込みやすいということです。

おまけ COPYのコツ

これも上記公式ドキュメントに記載の話です。

Imageキャッシュをできるだけ利用できるようにすることを意識してDockerfileを記述しましょう。

ダメな例
COPY . /tmp/
RUN pip install --requirement /tmp/requirements.txt
改良
COPY requirements.txt /tmp/
RUN pip install --requirement /tmp/requirements.txt
COPY . /tmp/

2つの違いがImageキャッシュ利用にどう関わるか理解しておく必要があります。
RUN pip install --requirement /tmp/requirements.txtrequirements.txtの差分のみに影響されて実行されるべきです。
ダメな方はそれ以外の.以下の何かが変更されるたび、COPY . /tmp/のレイヤーのImageコミットが変わるので、RUN pip installは以前のキャッシュを利用することができず毎回ダウンロードしてインストールすることになってしまいます。

参考

49
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
momotaro98
サーバサイド寄りのWebエンジニアです。QiitaでLGTMをもらうことで生を実感します。
rarejob
明治神宮にあるオンライン英会話サービスを提供するベンチャー

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
49
Help us understand the problem. What is going on with this article?