4

We have a solution-wide folder that contains shared settings that each project needs.

I'm trying to copy the contents of that folder to the /app folder but it's not working

This is part of my dockerfile configuration:

FROM mcr.microsoft.com/dotnet/core/sdk:3.1-alpine3.12 AS build

### this is where I'm trying to copy the contents of Shared Settings to /app
WORKDIR '/src/Shared Settings'
COPY '/src/Shared Settings' /app

### this is part of the rest of the docker file, which works fine
WORKDIR /src
COPY . .
WORKDIR /src/OurProject.Server
RUN dotnet restore OurProject.Server.csproj
RUN dotnet build OurProject.Server.csproj -c Release -o /app

What do I need to change to get the contents of Shared Settings copied to the /app folder in my docker container?

DaveDev
  • 41,155
  • 72
  • 223
  • 385

3 Answers3

5

The Dockerfile documentation for the COPY directive notes that it has two forms, a space-separated form and a JSON-array form, and it notes

This latter [JSON array] form is required for paths containing whitespace.

So applying that to your specific path, you would get

COPY ["src/Shared Settings", "/app"]

This is broadly true in a Dockerfile in general: the only quoting in native Dockerfile syntax is to write things in a JSON array. Wrapping a WORKDIR or a COPY command in single quotes isn't documented as having an effect. A string-form RUN or CMD is an apparent exception to this, but only because these commands are run via a shell and there the shell's quoting rules apply.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thanks but this doesn't work (even though according to the documentation it should!) :/ There must be something else wrong. – DaveDev Mar 09 '22 at 00:26
  • Can you clarify what exactly does happen, when you say it "doesn't work"? Do you get an error from `docker build`? Is the directory missing when you run the container; and if so, how are you starting it? Is the directory you're trying to add a subdirectory of the directory containing the Dockerfile? – David Maze Mar 09 '22 at 10:53
  • I was running everthing with Visual Studio's run button so I wasn't seeing output. I changed it to build via the command line and now I see `#21 [build 7/7] COPY [src/Shared Settings/, /app]`, `#21 sha256:84551c91e9d61cab65cb11cfb976f1ef4a982ba9ad6ccee300062361b7142b52`, `#21 ERROR: "/src/Shared Settings" not found: not found` So it's telling me that the Shared Settings folder isn't found. But I _can_ manually navigate to it in the docker container's CLI and manually copy the files from Shared Settings to /app. So I don't see why the build can't do that. – DaveDev Mar 09 '22 at 23:19
  • ... and then after those messages, `failed to compute cache key: "/Shared Settings" not found: not found` – DaveDev Mar 09 '22 at 23:21
  • ... and to the question, " Is the directory you're trying to add a subdirectory of the directory containing the Dockerfile?", no - the Shared Settings directory exists on the same level as the directory containing the dockerfile. This implies to me that I should be referring to the parent directory, e.g. `../SharedSettings` but that still results in a 'not found' error – DaveDev Mar 10 '22 at 22:01
  • 1
    You can't `COPY ../anywhere` from a parent or sibling directory of the build-context directory. Also see [How to include files outside of Docker's build context?](https://stackoverflow.com/questions/27068596/how-to-include-files-outside-of-dockers-build-context). – David Maze Mar 10 '22 at 22:24
0

The COPY '/src/Shared Settings' /app command would fail because it is meant for copying from the build context (folder containing your Dockerfile). However, the path '/src/Shared Settings' suggests that you are building from the root directory of your host. If that src directory is not at the root /, but instead exists within a different folder (e.g. /path/to/your/folder_containing_src_and_Dockerfile/src) you should change the instruction in your Dockerfile to:

COPY 'src/Shared Settings' /app

This removes the leading / that causes confusion in the path for your command.

EDIT: if you are building from the src directory, just use the following instruction in your Dockerfile:

COPY 'Shared Settings' /app
Dharman
  • 30,962
  • 25
  • 85
  • 135
pcamach2
  • 443
  • 2
  • 13
  • Hi, thanks for this but it's not quite correct I think. With single quotes (as above): `failed to create LLB definition: failed to process "'Shared": unexpected end of statement while looking for matching single-quote`, with double quotes: `failed to create LLB definition: failed to process "\"Shared"`. Without quotes (e.g. **COPY Shared\ Settings /app**): `failed to compute cache key: "/Shared" not found: not found` – DaveDev Mar 24 '22 at 00:31
  • Hmm, does the syntax from @David Maze work for the second command? e.g.: `COPY ["Shared Settings", "/app"]` – pcamach2 Mar 24 '22 at 00:44
0

The COPY instruction is tightly linked to the context you will build this image in.

This is actually pointed in the documentation:

The docker build command builds Docker images from a Dockerfile and a “context”. A build’s context is the set of files located in the specified PATH or URL. The build process can refer to any of the files in the context. For example, your build can use a COPY instruction to reference a file in the context.

Source: https://docs.docker.com/engine/reference/commandline/build/#extended-description

This said, although one will usually do:

docker build .

You have to understand that, this last dot ., that you surely have seen Docker complain about, when you've forgotten providing it, in some occasion, is the actual context in which this build will happen.

You are not forced to have . — so the current directory — as your context though.

So, what you will have to aim at is to provide the right context, which will be a folder that would be a common ancestor between /src/Shared Settings and the folder your Dockerfile resides.

You could end up with a big downside, with the folder Shared Settings being only in src, because the only common ancestor you will find might force you to use / as your context, making you an humongous context and so a really heavy build.

To come around this, you can use a .dockerignore file, though, to ignore all unrelated folders but the one you are want to make use of; namely /src/Shared Settings and the folder containing your Dockerfile.

Also, as you change your context, mind that you will have to adapt the line

COPY . .

That will now read:

COPY name_of_the_folder_containing_the_Dockerfile .

Here is an example that you will have to adapt based on your actual folders hierarchy.

Here the folders hierarchy:

.
├── .dockerignore
└── src
    ├── docker
    │   └── Dockerfile
    └── shared_settings
        └── foo.conf

In the Dockerfile:

FROM alpine

COPY src/shared_settings /etc/opt/app

WORKDIR /opt/app
COPY src/docker .
## The new equivalent to your previous `COPY . .`

CMD ["ls","-l"]

Here is how the file .dockerignore does exclude the folder unrelated from the context:

**
!src/docker
!src/shared_settings

And, now I can either go in the folder src/docker and build with:

docker build -f Dockerfile ../..

Or go in the folder / and build with

docker build -f src/docker/Dockerfile .

The only important thing is that both the folder containing the Dockerfile and the folder shared_settings should be part of my context.

β.εηοιτ.βε
  • 33,893
  • 13
  • 69
  • 83