Help us understand the problem. What is going on with this article?

[docker] COPY とADD の違いを試してみた

More than 5 years have passed since last update.

概要

Dockerfile にCOPY とADD ってあるけど同じように見えるけどなにが違うのかわからないから調査とそのメモ

環境

  • OS : cent7.1
cat /etc/redhat-release
  # CentOS Linux release 7.1.1503 (Core)
  • docker : 1.8.1
[root@docker-engine /]# docker version
  # Client:
  #  Version:      1.8.1
  #  API version:  1.20
  #  Go version:   go1.4.2
  #  Git commit:   d12ea79
  #  Built:        Thu Aug 13 02:19:43 UTC 2015
  #  OS/Arch:      linux/amd64
  # 
  # Server:
  #  Version:      1.8.1
  #  API version:  1.20
  #  Go version:   go1.4.2
  #  Git commit:   d12ea79
  #  Built:        Thu Aug 13 02:19:43 UTC 2015
  #  OS/Arch:      linux/amd64

※ install はこちらを参照

ファイル構成

[root@docker-engine /]# tree /tmp/work/
  # /tmp/work/
  # ├── fuga-dir
  # │   ├── fuga-file
  # │   └── fuga-tar.tar
  # └── hoge-dir
  #     ├── current-file
  #     ├── current-tar-gz.tar.gz
  #     ├── current-tar.tar
  #     ├── current-zip.zip
  #     ├── Dockerfile
  #     └── test-dir
  #         ├── 400
  #         ├── 644
  #         ├── 775
  #         ├── 777
  #         ├── centos
  #         ├── no-permission.tar
  #         ├── sub-dir
  #         │   ├── sub-file
  #         │   └── sub-tar-gz.tgz
  #         └── test-tar.tar
  # 4 directories, 16 files

[root@docker-engine /]# ls -Rl /tmp/work/
  # /tmp/work/:
  # total 0
  # drwxr-xr-x 2 root root  41 Aug 27 20:48 fuga-dir
  # drwxr-xr-x 3 root root 129 Aug 27 20:59 hoge-dir
  # /tmp/work/fuga-dir:
  # total 16
  # -rw-r--r-- 1 root root    10 Aug 27 20:48 fuga-file
  # -rw-r--r-- 1 root root 10240 Aug 27 20:48 fuga-tar.tar
  # /tmp/work/hoge-dir:
  # total 28
  # -rw-r--r-- 1 root root    13 Aug 27 20:49 current-file
  # -rw-r--r-- 1 root root   132 Aug 27 20:49 current-tar-gz.tar.gz
  # -rw-r--r-- 1 root root 10240 Aug 27 20:49 current-tar.tar
  # -rw-r--r-- 1 root root   184 Aug 27 20:50 current-zip.zip
  # -rw-r--r-- 1 root root    35 Aug 27 20:54 Dockerfile
  # drwxr-xr-x 3 root root   116 Aug 27 20:59 test-dir
  # /tmp/work/hoge-dir/test-dir:
  # total 44
  # -r-------- 1 root   root     4 Aug 27 20:50 400
  # -rw-r--r-- 1 root   root     4 Aug 27 20:51 644
  # -rwxrwxr-x 1 root   root     4 Aug 27 20:51 775
  # -rwxrwxrwx 1 root   root     4 Aug 27 20:51 777
  # -rw-r--r-- 1 centos root     7 Aug 27 20:51 centos
  # -r-------- 1 root   root 10240 Aug 27 20:53 no-permission.tar
  # drwxr-xr-x 2 root   root    42 Aug 27 20:53 sub-dir
  # -rw-r--r-- 1 root   root 10240 Aug 27 20:52 test-tar.tar
  # /tmp/work/hoge-dir/test-dir/sub-dir:
  # total 8
  # -rw-r--r-- 1 root root   9 Aug 27 20:51 sub-file
  # -rw-r--r-- 1 root root 127 Aug 27 20:52 sub-tar-gz.tgz

test 1 : COPY

Dockerfile
FROM centos:7
MAINTAINER hihihiroro

RUN mkdir /tmp/work

COPY current-file /tmp/work/
COPY current-tar-gz.tar.gz /tmp/work/
COPY current-tar.tar /tmp/work/
COPY current-zip.zip /tmp/work/

build

[root@docker-engine hoge-dir]# cd /tmp/work/hoge-dir/
[root@docker-engine hoge-dir]# docker build -t current-copy .
  # Sending build context to Docker daemon 45.57 kB
  # Step 0 : FROM centos:7
  #  ---> 7322fbe74aa5
  # Step 1 : MAINTAINER hihihiroro
  #  ---> Running in 2c74398bbffd
  #  ---> 8695ea6407ce
  # Removing intermediate container 2c74398bbffd
  # Step 2 : RUN mkdir /tmp/work
  #  ---> Running in b59cbe5bc8fa
  #  ---> 0aaaef30832d
  # Removing intermediate container b59cbe5bc8fa
  # Step 3 : COPY current-file /tmp/work/
  #  ---> 76cb089a5042
  # Removing intermediate container abb2b43ae9fe
  # Step 4 : COPY current-tar-gz.tar.gz /tmp/work/
  #  ---> 06efc812b96b
  # Removing intermediate container eacd86fe45ba
  # Step 5 : COPY current-tar.tar /tmp/work/
  #  ---> 3d35a884dc2a
  # Removing intermediate container ded82fa499db
  # Step 6 : COPY current-zip.zip /tmp/work/
  #  ---> c000eb1c0bc9
  # Removing intermediate container c8eb66aa3918
  # Successfully built c000eb1c0bc9

結果確認 : test1

[root@docker-engine hoge-dir]# docker run -it current-copy /bin/bash
[root@4c7712046eeb /]# tree /tmp/work/
  # /tmp/work/
  # |-- current-file
  # |-- current-tar-gz.tar.gz
  # |-- current-tar.tar
  # `-- current-zip.zip
  # 0 directories, 4 files
[root@4c7712046eeb /]# ls -Rl /tmp/work/
  # /tmp/work/:
  # total 24
  # -rw-r--r-- 4 root root    13 Aug 27 11:49 current-file
  # -rw-r--r-- 3 root root   132 Aug 27 11:49 current-tar-gz.tar.gz
  # -rw-r--r-- 2 root root 10240 Aug 27 11:49 current-tar.tar
  # -rw-r--r-- 1 root root   184 Aug 27 11:50 current-zip.zip

ユーザもファイル形式もそのまま指定したディレクトリにコピーされた

test2 : ADD

Dockerfile
FROM centos:7
MAINTAINER hihihiroro

RUN mkdir /tmp/work

ADD current-file /tmp/work/
ADD current-tar-gz.tar.gz /tmp/work/
ADD current-tar.tar /tmp/work/
ADD current-zip.zip /tmp/work/

build

[root@docker-engine hoge-dir]# cd /tmp/work/hoge-dir/
[root@docker-engine hoge-dir]# docker build -t current-add .
  # Sending build context to Docker daemon 45.57 kB
  # Step 0 : FROM centos:7
  #  ---> 7322fbe74aa5
  # Step 1 : MAINTAINER hihihiroro
  #  ---> Using cache
  #  ---> 8695ea6407ce
  # Step 2 : RUN mkdir /tmp/work
  #  ---> Using cache
  #  ---> 0aaaef30832d
  # Step 3 : ADD current-file /tmp/work/
  #  ---> 3f44522614ff
  # Removing intermediate container e69d27a714f6
  # Step 4 : ADD current-tar-gz.tar.gz /tmp/work/
  #  ---> 1917377fc30c
  # Removing intermediate container 0798cb9729db
  # Step 5 : ADD current-tar.tar /tmp/work/
  #  ---> 7f1a4df66306
  # Removing intermediate container b61bfaa2cf90
  # Step 6 : ADD current-zip.zip /tmp/work/
  #  ---> e8bcd18517fa
  # Removing intermediate container 91778099e5b4
  # Successfully built e8bcd18517fa

結果確認 : test2

[root@docker-engine hoge-dir]# docker run -it current-add /bin/bash
[root@458d2527db24 /]# tree /tmp/work/
  # /tmp/work/
  # |-- current-file
  # |-- current-tar
  # |-- current-tar-gz
  # `-- current-zip.zip
  # 0 directories, 4 files
[root@458d2527db24 /]# ls -Rl /tmp/work/
  # /tmp/work/:
  # total 16
  # -rw-r--r-- 4 root root  13 Aug 27 11:49 current-file
  # -rw-r--r-- 2 root root  12 Aug 27 11:49 current-tar
  # -rw-r--r-- 3 root root  15 Aug 27 11:49 current-tar-gz
  # -rw-r--r-- 1 root root 184 Aug 27 11:50 current-zip.zip

みごとにtar とtar.gz は展開されているがzip はそのまま。

では調子に乗ってディレクトリを指定してCOPY とADD の違いも見てみる。

test3 : ディレクトリを指定してCOPY

Dockerfile
FROM centos:7
MAINTAINER hihihiroro

RUN mkdir /tmp/work

COPY test-dir /tmp/work/

build

[root@docker-engine hoge-dir]# docker build -t copy .
  # Sending build context to Docker daemon 45.57 kB
  # Step 0 : FROM centos:7
  #  ---> 7322fbe74aa5
  # Step 1 : MAINTAINER hihihiroro
  #  ---> Using cache
  #  ---> 8695ea6407ce
  # Step 2 : RUN mkdir /tmp/work
  #  ---> Using cache
  #  ---> 0aaaef30832d
  # Step 3 : COPY test-dir /tmp/work/
  #  ---> eeb592905d53
  # Removing intermediate container a87775e06605
  # Successfully built eeb592905d53

結果確認 : test3

[root@docker-engine hoge-dir]# docker run -it copy /bin/bash
[root@1782fb5690c3 /]# tree /tmp/work/
  # /tmp/work/
  # |-- 400
  # |-- 644
  # |-- 775
  # |-- 777
  # |-- centos
  # |-- no-permission.tar
  # |-- sub-dir
  # |   |-- sub-file
  # |   `-- sub-tar-gz.tgz
  # `-- test-tar.tar
  # 1 directory, 9 files
[root@1782fb5690c3 /]# ls -Rl /tmp/work/
  # /tmp/work/:
  # total 44
  # -r-------- 1 root root     4 Aug 27 11:50 400
  # -rw-r--r-- 1 root root     4 Aug 27 11:51 644
  # -rwxrwxr-x 1 root root     4 Aug 27 11:51 775
  # -rwxrwxrwx 1 root root     4 Aug 27 11:51 777
  # -rw-r--r-- 1 root root     7 Aug 27 11:51 centos
  # -r-------- 1 root root 10240 Aug 27 11:53 no-permission.tar
  # drwxr-xr-x 2 root root    42 Aug 27 11:53 sub-dir
  # -rw-r--r-- 1 root root 10240 Aug 27 11:52 test-tar.tar
  # /tmp/work/sub-dir:
  # total 8
  # -rw-r--r-- 1 root root   9 Aug 27 11:51 sub-file
  # -rw-r--r-- 1 root root 127 Aug 27 11:52 sub-tar-gz.tgz

test-dir 配下がコピーされて、test-dir 自体はコピーされていない。
centos ファイルのユーザが centos -> root になっている。

Docker Docs に書いてあった
All new files and directories are created with a UID and GID of 0.

ADD もテストしてみる。

test4 : ディレクトリを指定してADD

Dockerfile
FROM centos:7
MAINTAINER hihihiroro

RUN mkdir /tmp/work

ADD test-dir /tmp/work/

build

[root@docker-engine hoge-dir]# docker build -t add .
  # Sending build context to Docker daemon 45.57 kB
  # Step 0 : FROM centos:7
  #  ---> 7322fbe74aa5
  # Step 1 : MAINTAINER hihihiroro
  #  ---> Using cache
  #  ---> 8695ea6407ce
  # Step 2 : RUN mkdir /tmp/work
  #  ---> Using cache
  #  ---> 0aaaef30832d
  # Step 3 : ADD test-dir /tmp/work/
  #  ---> 6c9f268c5bfd
  # Removing intermediate container c88178c28809
  # Successfully built 6c9f268c5bfd

結果確認 : test4

[root@docker-engine hoge-dir]# docker run -it add /bin/bash
[root@63e9020ce0a9 /]# tree /tmp/work/
  # /tmp/work/
  # |-- 400
  # |-- 644
  # |-- 775
  # |-- 777
  # |-- centos
  # |-- no-permission.tar
  # |-- sub-dir
  # |   |-- sub-file
  # |   `-- sub-tar-gz.tgz
  # `-- test-tar.tar
  # 1 directory, 9 files
[root@63e9020ce0a9 /]# ls -Rl /tmp/work/
  # /tmp/work/:
  # total 44
  # -r-------- 1 root root     4 Aug 27 11:50 400
  # -rw-r--r-- 1 root root     4 Aug 27 11:51 644
  # -rwxrwxr-x 1 root root     4 Aug 27 11:51 775
  # -rwxrwxrwx 1 root root     4 Aug 27 11:51 777
  # -rw-r--r-- 1 root root     7 Aug 27 11:51 centos
  # -r-------- 1 root root 10240 Aug 27 11:53 no-permission.tar
  # drwxr-xr-x 2 root root    42 Aug 27 11:53 sub-dir
  # -rw-r--r-- 1 root root 10240 Aug 27 11:52 test-tar.tar
  # /tmp/work/sub-dir:
  # total 8
  # -rw-r--r-- 1 root root   9 Aug 27 11:51 sub-file
  # -rw-r--r-- 1 root root 127 Aug 27 11:52 sub-tar-gz.tgz

test-dir 配下がコピーされて、test-dir 自体はコピーされていない。
おや?centos ファイルのユーザが centos -> root になっている。

こっちもDocker Docs に書いてあった。
All new files and directories are created with a UID and GID of 0.

ここまでは一緒だが、ファイルで指定した際にはtar が展開されていたのに、今回はそのままコピーされている。

まとめ

共通点

  • コピー元がファイルの場合ファイルのパーミッションはコピー元を引き継ぎ、ユーザはroot でコピーをする。
  • コピー元がディレクトリの場合ADD とCOPY に差分はない?(要検証)

差分

  • コピー元がファイルかつサポートされているファイル形式(identity, gzip, bzip2 or xz)の場合コピー先で展開される。

反省

ADD にはコピー元をURL も指定できる、他にもワイルドカードが使えるなどの違いもあるらしい。
また、時間ができた際にはそこらへんも調査しよう。

参考

COPY DOCS
ADD DOCS

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