Posted at

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

More than 3 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