Dockerfile copy keep subdirectory structure
Asked Answered
M

6

549

I'm trying to copy a number of files and folders to a docker image build from my localhost.

The files are like this:

folder1/
    file1
    file2
folder2/
    file1
    file2

I'm trying to make the copy like this:

COPY files/* /files/

However, all of the files from folder1/ and folder2/ are placed in /files/ directly, without their folders:

files/
    file1
    file2

Is there a way in Docker to keep the subdirectory structure as well as copying the files into their directories? Like this:

files/
    folder1/
        file1
        file2
    folder2/
        file1
        file2
Marble answered 13/5, 2015 at 13:9 Comment(3)
could you clarify what result you got and what result you expect?Kenward
Yes, I agree, @Kenward . The answer is clear, but the question is not.Lennalennard
@Thomasleveil, it seems they want to preserve the directories, but the star makes Docker to copy the internals of the directories instead.Hampshire
A
745

Remove star from COPY, with this Dockerfile:

FROM ubuntu
COPY files/ /files/
RUN ls -la /files/*

Structure is there:

$ docker build .
Sending build context to Docker daemon 5.632 kB
Sending build context to Docker daemon 
Step 0 : FROM ubuntu
 ---> d0955f21bf24
Step 1 : COPY files/ /files/
 ---> 5cc4ae8708a6
Removing intermediate container c6f7f7ec8ccf
Step 2 : RUN ls -la /files/*
 ---> Running in 08ab9a1e042f
/files/folder1:
total 8
drwxr-xr-x 2 root root 4096 May 13 16:04 .
drwxr-xr-x 4 root root 4096 May 13 16:05 ..
-rw-r--r-- 1 root root    0 May 13 16:04 file1
-rw-r--r-- 1 root root    0 May 13 16:04 file2

/files/folder2:
total 8
drwxr-xr-x 2 root root 4096 May 13 16:04 .
drwxr-xr-x 4 root root 4096 May 13 16:05 ..
-rw-r--r-- 1 root root    0 May 13 16:04 file1
-rw-r--r-- 1 root root    0 May 13 16:04 file2
 ---> 03ff0a5d0e4b
Removing intermediate container 08ab9a1e042f
Successfully built 03ff0a5d0e4b
Axis answered 13/5, 2015 at 16:8 Comment(8)
But what if I need just some files like COPY files/*1 /files/?Jara
Will this also overwrite existing files in that directory?Hedy
@chander, yes, existing files will be overwrittenAxis
It's important to note that the secret sauce here is that there is ONE source directory, and ONE target directory specified. Any other combination copies the contents of the source directory(ies) to the target directory.Amalgam
I wasn't able to see the output of RUN ls -la /files/* directly from the console output of docker build. So I instead went ssh to the container directly to do ls directly on the host, with docker exec -it <container name> /bin/bashJelsma
RUN find . to list files in subdirectoriesTicket
This did not work for me with when building from ibmcom/websphere-liberty:kernel-java8-ibmjava-ubi on macos. Neither the rest of solutions in this post did though.Bicycle
Going on the record that it's absurd that ADD dir/* . will flatten dir into the current WORKDIR. I can't even think of a use case for that.Indigo
M
95

To merge a local directory into a directory within an image, do this. It will not delete files already present within the image. It will only add files that are present locally, overwriting the files in the image if a file of the same name already exists.

COPY ./local-path/. /image-path/
Mink answered 8/7, 2019 at 19:23 Comment(1)
This is the best solution because in one command you can copy an entire filesystem's worth of changes into an image layer. I keep a /resources directory in my source repo that mirrors the parts of the image filesystem to be added/overwritten. Then just add it all in one shot: COPY resources/./ /Morgen
O
94

Alternatively you can use a "." instead of *, as this will take all the files in the working directory, include the folders and subfolders:

FROM ubuntu
COPY . /
RUN ls -la /
Offering answered 29/11, 2018 at 12:25 Comment(5)
will that include hidden files and dirs like '.git' directory?Unwilled
@BrunoNegrãoZica, you could use .dockerignore file to specify what files/folders you would like to be ignored during copy operation. It's late, but hope it would be helpful for someone elsePestilent
COPY . ./ worked for me instead of COPY . / with Docker Desktop 4.0.1Grays
".dockerfile" with: WORKDIR /usr/src/app COPY . .Exalted
@smoq : these are two different statements which probably both worked, but only one of them did what you were expecting. The first copies files to the CWD in the container, the second copies them to the root directory in the container.Amuck
A
12

I could not get any of these answers to work for me. I had to add a dot for the current directory, so that the working docker file looks like:

FROM ubuntu 
WORKDIR /usr/local
COPY files/ ./files/

Also using RUN ls to verify wasn't working for me and getting it to work was looking really involved, a much easier way to verify what is in the docker file is to run an interactive shell and check out what is in there, using docker run -it <tagname> sh.

Annitaanniversary answered 18/8, 2022 at 17:11 Comment(0)
C
6

If you want to copy a source directory entirely with the same directory structure, Then don't use a star(*). Write COPY command in Dockerfile as below.

COPY . destinatio-directory/ 
Cajeput answered 29/10, 2020 at 3:51 Comment(2)
OP specifically asked about a directory within the current directory and not the contents of the current directory. COPY files/ /files/ without a wildcard is the answer.Genome
TheZeke did coment something to keep an eye on. However, this is also a good reminder on how simple it is to copy the context to a, say, /var/www/html destination.Kimmi
M
0

Check if the Q1 2024 Dockerfile 1.7.0 release would support this use-case.

PR 3001 does mention:

COPY [--parents[=<boolean>]] <src>... <dest>

The --parents flag preserves parent directories for src entries.
This flag defaults to false.

# syntax=docker/dockerfile-upstream:master-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

This behavior is analogous to the Linux cp utility's --parents flag.

Note that, without the --parents flag specified, any filename collision will fail the Linux cp operation with an explicit error message (cp: will not overwrite just-created './x/a.txt' with './y/a.txt'), where the Buildkit will silently overwrite the target file at the destination.

While it is possible to preserve the directory structure for COPY instructions consisting of only one src entry, usually it is more beneficial to keep the layer count in the resulting image as low as possible.
Therefore, with the --parents flag, the Buildkit is capable of packing multiple COPY instructions together, keeping the directory structure intact.

Mercuri answered 5/3, 2024 at 22:14 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.