Reputation: 6116
I tried the following command in my Dockerfile: COPY * /
and got mighty surprised at the result. Seems the naive docker code traverses the directories from the glob and then dumps the each file in the target directory while respectfully ignoring my directory structure.
At least that is how I understand this ticket and it certainly corresponds to the result I got.
I guess the only reason this behavior can still exist must be that there is some other way this should be done. But it is not so easy for a bear of very little brain to understand how, does anyone know?
Upvotes: 168
Views: 455790
Reputation: 1323045
2016: As mentioned in your ticket:
You have
COPY files/* /test/
which expands toCOPY files/dir files/file1 files/file2 files/file /test/
.
If you split this up into individualCOPY
commands (e.g.,COPY files/dir /test/
) you'll see that (for better or worse)COPY
will copy the contents of each argumentdir
into the destination directory. Not the argumentdir
itself, but the contents.I'm not thrilled with that fact that
COPY
doesn't preserve the top-level dir but its been that way for a while now.
So in the name of preserving a backward compatibility, it is not possible to COPY
/ADD
a directory structure.
The only workaround would be a series of RUN mkdir -p /x/y/z
to build the target directory structure, followed by a series of docker ADD
(one for each folder to fill).
(ADD
, not COPY
, as per comments)
2023: moby/buildkit
PR 3001 proposes adding --parents
opt-in flag for ADD
/COPY
, merged with commit 9dd188b:
COPY [--parents[=<boolean>]] <src>... <dest>
The
--parents
flag preserves parent directories forsrc
entries. This flag defaults tofalse
.# syntax=docker/dockerfile:1.7-labs FROM scratch COPY ./x/a.txt ./y/a.txt /no_parents/ COPY --parents ./x/a.txt ./y/a.txt /parents/ # /no_parents/a.txt # /parents/x/a.txt # /parents/y/a.txt
The results are encouraging:
I just tried the feature and I have to say to everyone who has been involved: Thank you so much!
We have a JS monorepo and so far to split dependency installation and building into 2 stages, we had to either manually specify allpackage.json
and lock files manually or use scripts to isolate these files in a separate folder before copying it into the build context.Now it's just a
COPY --parents pnpm-workspace.yaml **/package.json **/pnpm-lock.yaml ./
away, and I get a super nice tree that I can justpnpm install
.
The behavior was confusing because it copied files relative to the destination directory, even when the
dst
was specified as an absolute path and had a common path prefix with thesrc
directory. I'm guessing this is the intended behavior.For example, the following command copied the files into
/usr/src/app/packages/**usr/src/app/packages**/**/dist
.COPY --parents --from=build /usr/src/app/packages/**/dist /usr/src/app/packages
I managed to fix it with the following command:
COPY --parents --from=build /usr/src/app/packages/**/dist /
See COPY --parents
, not yet available in stable syntax, use docker/dockerfile:1.7-labs
version.
Upvotes: 27
Reputation: 16484
If you want to copy a subdirectory, you must repeat the name of the subdirectory in the destination.
For example, I wanted to copy the directory example_subdirectory
into the working directory on the Docker container side.
This does not work:
workdir /example
copy ./example_subdirectory .
It does not work because it copies the contents of example_subdirectory
but not the directory example_subdirectory
itself.
copy ./example_subdirectory ./example_subdirectory
This will create a directory called example_subdirectory
in the destination on the Docker side.
The copy command has different semantics to the Linux (and also Windows) cp
command, which is confusing.
Upvotes: 0
Reputation: 51
FROM openjdk:8-jdk-alpine
RUN apk update && apk add wget openssl lsof procps curl
RUN apk update
RUN mkdir -p /apps/agent
RUN mkdir -p /apps/lib
ADD ./app/agent /apps/agent
ADD ./app/lib /apps/lib
ADD ./app/* /apps/app/
RUN ls -lrt /apps/app/
CMD sh /apps/app/launch.sh
Within my Dockerfile, I'm copying my ./apps/agent
and ./apps/lib
directories to /apps/agent
and /apps/lib
directories.
Upvotes: 4
Reputation: 4837
ADD
(docs)The ADD
command can accept as a <src>
parameter:
ADD folder /path/inside/your/container
or
tar -cvzf newArchive.tar.gz /path/to/your/folder
You would then add a line to your Dockerfile like this:
ADD /path/to/archive/newArchive.tar.gz /path/inside/your/container
Notes:
ADD
will automatically extract your archive.Upvotes: 117
Reputation: 1643
use ADD
instead of COPY
. Suppose you want to copy everything in directory src from host to directory dst from container:
ADD src dst
Note: directory dst will be automatically created in container.
Upvotes: 35
Reputation: 15
Suppose you want to copy the contents from a folder where you have docker file into your container. Use ADD:
RUN mkdir /temp
ADD folder /temp/Newfolder
it will add to your container with temp/newfolder
folder is the folder/directory where you have the dockerfile, more concretely, where you put your content and want to copy that.
Now can you check your copied/added folder by runining container and see the content using ls
Upvotes: -3
Reputation: 1346
the simplest way:
sudo docker cp path/on/your/machine adam_ubuntu:/root/path_in_container
Note putting into the root path if you are copying something that needs to be picked up by the root using ~.
Upvotes: -7
Reputation: 1160
I don't completely understand the case of the original poster but I can proof that it's possible to copy directory structure using COPY in Dockerfile.
Suppose you have this folder structure:
folder1
file1.html
file2.html
folder2
file3.html
file4.html
subfolder
file5.html
file6.html
To copy it to the destination image you can use such a Dockerfile content:
FROM nginx
COPY ./folder1/ /usr/share/nginx/html/folder1/
COPY ./folder2/ /usr/share/nginx/html/folder2/
RUN ls -laR /usr/share/nginx/html/*
The output of docker build .
as follows:
$ docker build --no-cache .
Sending build context to Docker daemon 9.728kB
Step 1/4 : FROM nginx
---> 7042885a156a
Step 2/4 : COPY ./folder1/ /usr/share/nginx/html/folder1/
---> 6388fd58798b
Step 3/4 : COPY ./folder2/ /usr/share/nginx/html/folder2/
---> fb6c6eacf41e
Step 4/4 : RUN ls -laR /usr/share/nginx/html/*
---> Running in face3cbc0031
-rw-r--r-- 1 root root 494 Dec 25 09:56 /usr/share/nginx/html/50x.html
-rw-r--r-- 1 root root 612 Dec 25 09:56 /usr/share/nginx/html/index.html
/usr/share/nginx/html/folder1:
total 16
drwxr-xr-x 2 root root 4096 Jan 16 10:43 .
drwxr-xr-x 1 root root 4096 Jan 16 10:43 ..
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file1.html
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file2.html
/usr/share/nginx/html/folder2:
total 20
drwxr-xr-x 3 root root 4096 Jan 16 10:43 .
drwxr-xr-x 1 root root 4096 Jan 16 10:43 ..
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file3.html
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file4.html
drwxr-xr-x 2 root root 4096 Jan 16 10:33 subfolder
/usr/share/nginx/html/folder2/subfolder:
total 16
drwxr-xr-x 2 root root 4096 Jan 16 10:33 .
drwxr-xr-x 3 root root 4096 Jan 16 10:43 ..
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file5.html
-rwxr-xr-x 1 root root 7 Jan 16 10:32 file6.html
Removing intermediate container face3cbc0031
---> 0e0062afab76
Successfully built 0e0062afab76
Upvotes: 16
Reputation: 49
Replace the * with a /
So instead of
COPY * <destination>
use
COPY / <destination>
Upvotes: 0
Reputation: 8328
Like @Vonc said, there is no possibility to add a command like as of now. The only workaround is to mention the folder, to create it and add contents to it.
# add contents to folder
ADD src $HOME/src
Would create a folder called src in your directory and add contents of your folder src into this.
Upvotes: 41