1. Overview

In this article, we’ll learn to copy a directory into a Docker image preserving the subdirectory structure.

2. Copy a Local Directory to the Image

Let’s create the following file tree:

|   Dockerfile
|   
\---folder1
    +---subfolder1
    |       file1.txt
    |       
    \---subfolder2
            file2.txt

This can be done by running the following commands:

$ mkdir folder1
$ cd folder1
$ mkdir subfolder1
$ cd subfolder1
$ touch file1.txt
$ cd ..
$ mkdir subfolder2
$ cd subfolder2
$ touch file2.txt
$ cd ../..

We’ll now open our Dockerfile with:

$ touch Dockerfile

Then, let’s insert the following:

FROM ubuntu:latest
COPY folder1/ /workdir/
RUN ls --recursive /workdir/

Let’s understand the content line by line:

  • the first line states that we’re using the latest ubuntu image as our base image
  • the second line copies the content of the folder1 directory into the workdir directory of the image. If workdir doesn’t exist yet, it will be created
  • the third line executes the ls command inside the image’s shell to recursively list all subdirectories’ content of the workdir folder

We can now build our Docker image:

$ docker build .
#4 [1/3] FROM docker.io/library/ubuntu:latest
#6 [2/3] COPY folder1/ /workdir/
#7 [3/3] RUN ls --recursive /workdir/
#7 0.324 /workdir/:
#7 0.324 subfolder1
#7 0.324 subfolder2
#7 0.324
#7 0.324 /workdir/subfolder1:
#7 0.324 file1.txt
#7 0.324
#7 0.324 /workdir/subfolder2:
#7 0.324 file2.txt

As expected, recursively printing the content of workdir highlighted that it contains all subdirectories and files of folder1.

3. Merge a Local Directory Into the Image

Let’s now slightly update our file tree to match the following:

|   Dockerfile
|   
+---folder1
|   +---subfolder1
|   |       file1.txt
|   |       
|   \---subfolder2
|           file2.txt
|           
\---folder2
        file3.txt

In order to do this modification, we’ll run the following commands:

$ mkdir folder2
$ cd folder2
$ touch file3.txt
$ cd ..

We’ll now want to merge the content of folder2 into the workdir of the image afterwards. Let’s complete our Dockerfile:

FROM ubuntu:latest
COPY folder1/ /workdir/
RUN ls --recursive /workdir/
COPY folder2/ /workdir/
RUN ls --recursive /workdir/

The second COPY instruction won’t remove the previously added files. Let’s build our image to check this behaviour:

$ docker build .
#4 [1/5] FROM docker.io/library/ubuntu:latest
#6 [2/5] COPY folder1/ /workdir/
#7 [3/5] RUN ls --recursive /workdir/
#8 [4/5] COPY folder2/ /workdir/
#9 [5/5] RUN ls --recursive /workdir/
#9 0.398 /workdir/:
#9 0.398 file3.txt
#9 0.398 subfolder1
#9 0.398 subfolder2
#9 0.398
#9 0.398 /workdir/subfolder1:
#9 0.398 file1.txt
#9 0.398
#9 0.398 /workdir/subfolder2:
#9 0.398 file2.txt

As the log shows, all the subdirectories of folder1 and folder2 have indeed been copied to workdir.

As an additional note, we chose this example for the sake of demonstrating the merging behavior. If all we’d wanted was to copy the content of both folder1 and folder2 to the workdir directory of the image at the same time, we’d take advantage of the fact that COPY can accept multiple sources:

FROM ubuntu:latest
COPY folder1/ folder2/ /workdir/
RUN ls --recursive /workdir/

4. Conclusion

In this tutorial, we’ve seen how we can copy local directories to a Docker image while keeping their subdirectory structure.

As always, the code can be found over on GitHub.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.