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

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

# 環境
* OS : cent7.1

```bash
cat /etc/redhat-release
  # CentOS Linux release 7.1.1503 (Core)
```
* docker : 1.8.1

```bash
[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 は[こちら](https://docs.docker.com/installation/centos/)を参照

# ファイル構成
```bash
[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
``` bash: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

```bash
[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
```bash
[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
``` bash: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

```bash
[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
```bash
[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
```bash: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
```bash
[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](https://docs.docker.com/reference/builder/#copy) に書いてあった
> _All new files and directories are created with a UID and GID of 0._

ADD もテストしてみる。

# test4 : ディレクトリを指定してADD
```bash:Dockerfile
FROM centos:7
MAINTAINER hihihiroro

RUN mkdir /tmp/work

ADD test-dir /tmp/work/
```

build

```bash
[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
```bash
[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](https://docs.docker.com/reference/builder/#add) に書いてあった。
> 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](https://docs.docker.com/reference/builder/#copy)
[ADD DOCS](https://docs.docker.com/reference/builder/#add)