The following Dockerfile
contains four COPY
layers:
COPY README.md ./
COPY package.json ./
COPY gulpfile.js ./
COPY __BUILD_NUMBER ./
How to copy these files using one layer instead? The following was tried:
COPY [
"__BUILD_NUMBER ./",
"README.md ./",
"gulpfile ./",
"another_file ./",
]
COPY README.md package.json gulpfile.js __BUILD_NUMBER ./
or
COPY ["__BUILD_NUMBER", "README.md", "gulpfile", "another_file", "./"]
You can also use wildcard characters in the sourcefile specification. See the docs for a little more detail.
Directories are special! If you write
COPY dir1 dir2 ./
that actually works like
COPY dir1/* dir2/* ./
If you want to copy multiple directories (not their contents) under a destination directory in a single command, you'll need to set up the build context so that your source directories are under a common parent and then COPY
that parent.
COPY <all> <the> <things> <last-arg-is-destination>
But here is an important excerpt from the docs:
If you have multiple Dockerfile steps that use different files from your context, COPY them individually, rather than all at once. This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy
It might be worth mentioning that you can also create a .dockerignore
file, to exclude the files and directories that you don't want to copy:
https://docs.docker.com/engine/reference/builder/#dockerignore-file
Before the docker CLI sends the context to the docker daemon, it looks for a file named .dockerignore in the root directory of the context. If this file exists, the CLI modifies the context to exclude files and directories that match patterns in it. This helps to avoid unnecessarily sending large or sensitive files and directories to the daemon and potentially adding them to images using ADD or COPY.
simple
COPY README.md package.json gulpfile.js __BUILD_NUMBER ./
from the doc
If multiple resources are specified, either directly or due to the use of a wildcard, then must be a directory, and it must end with a slash /.
The original answer warns about an exception handling directories. https://stackoverflow.com/a/30316600/3257491
If you want to achieve this with directories where you just want to include one or more directories and zero or more specific files you can use .dockerignore
:
.dockerignore
file to ignore everything except src
directory, test
directory package.json
file and package-lock.json
file:
*
!src
!test
!package.json
!package-lock.json
Then Dockerfile
:
COPY . ./
This will include just the files included in exceptions in the .dockerignore
file.
To make it review friendly, you may need a multiline COPY
command. E.g. if the list of files to copy is very long.
Backslash escaping end of lines treats this like this:
COPY __BUILD_NUMBER \
README.md \
gulpfile \
another_file \
./
I could find an example with backslash for RUN
command, but not for COPY
. It works though for COPY
as well.
Success story sharing
tar
archive, and adding it with ADD.