tags: devops, docker, dockerfile
ADD
has more features than COPY
but it is suggested to use COPY
since you seldomly
use extra features provided by ADD
and the feature may give you unexpected result.
ADD
supports adds file from remote URL and extracts a directory from a tarball.
FROM debian:10
ADD pgbouncer-1.14.0.tar.gz /app/pgbouncer
RUN find /app
Above Dockerfile will extract the tar.gz
package and place it under /app/pgbouncer
so
that you'll get file like /app/pgbouncer/pgbouncer-1.14.0/src/xxx
.
If you simply replace all COPY
with ADD
, you won't get problem at most time but you
may extract tarballs unexpectedly.
So COPY
is suggested and use only ADD
when you need its special features.
Some tips about COPY
:
-
You don't need to
RUN mkdir xxx
for theCOPY
target, you canCOPY . /a/b/c/d/e
and docker will create directories for you. -
directory and slash. You do need to add slash for command like
COPY dir1 /app
. It will copy all content indir1
to/app
, you won't get path like/app/dir1
. It is same asCOPY dir1 /app/
andCOPY dir1/ /app/
.
If you want /app/dir1
, you need COPY dir1 /app/dir1
.
-
slash matters when copy single file like
COPY nginx.conf /etc/nginx/
. You MUST add/
suffix to indicate that target is a directory, otherwise it will treat target as a regular file if it is not existed. -
You CAN NOT copy multiple directories to target directory.
COPY dir1 dir2 /app/
works but it actually something likecopy dir1/* dir2/* /app/
and you won't get path like/app/dir1/xxx
and/app/dir2/xxx
. You have to use twoCOPY
commands.COPY dir1 /app/dir1 COPY dir2 /app/dir2
And you'll get error for COPY dir1 dir2 /app
since you need to use /app/
to specify
that the target is a directory but not a plain file.
- chown supports. From docker 17.09, you can use
COPY --chown=user:group
to change owner of added files. It saves an extraRUN chown
.
The docker buildkit is integrated to docker since 18.06. You can enable it via
DOCKER_BUILDKIT=1 docker build
.
And for dockerfile, you need to add #syntax=docker/dockerfile:1.2
at beginning to enable
it.
Sometimes, you may want to share some directories across multiple building, for example,
yarn cache directory, maven cache, go build cache, pip download cache. The dockerfile
doesn't support feature like docker run -v host_volume:container_volume
. However, the
buildkit supports RUN --mount=type=cache,target=/xxxx
sytax so that /xxxx
directory
will be cached and reused across buildings. For example:
RUN --mount=type=cache,target=/root/.m2 mvn clean package
By this way, the downloaded packages will be cached in /root/.m2
volume. This volume
is shared even though you changed dockerfile name or target image name.