如何通过Dockerfile将文件夹内容复制到/app目录?

4
我们有一个解决方案范围的文件夹,其中包含每个项目都需要的共享设置。
我正在尝试将该文件夹的内容复制到/app文件夹,但它不起作用。
这是我的dockerfile配置的一部分:
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

我需要更改什么才能将 Shared Settings 的内容复制到我的 Docker 容器中的 /app 文件夹中?

尝试转义空格:COPY "/src/Shared\ Settings" /app - James McPherson
这就是为什么我用引号括起来的原因。我会尝试一下。 - DaveDev
没有,不起作用,带引号或不带都一样。 - DaveDev
我相信这里已经有答案了:https://dev59.com/IFMI5IYBdhLWcg3wXaPZ - James McPherson
3个回答

5
Dockerfile文档中 COPY 指令有两种形式,一种是使用空格分隔的形式,另一种是使用JSON数组的形式。文档指出,对于包含空格的路径,必须使用后者即JSON数组形式。因此,针对您特定的路径,您应该使用如下形式:
COPY ["src/Shared Settings", "/app"]

总的来说,在Dockerfile中,引号只用于将内容写成JSON数组的形式。在单引号中包含WORKDIRCOPY命令并没有被文档记录为有影响的。然而,通过shell运行的RUNCMD命令则是一个明显的例外,因为这些命令是通过shell运行的,所以引用规则应用于shell。


谢谢,但这不起作用(尽管根据文档它应该!):/ 必须有其他问题。 - DaveDev
你能澄清一下当你说“不起作用”时到底发生了什么吗?你是否从docker build收到错误信息?当你运行容器时,目录是否丢失;如果是这样,你是如何启动它的?你尝试添加的目录是否是包含Dockerfile的目录的子目录? - David Maze
我一直使用Visual Studio的运行按钮来运行所有内容,所以我没有看到输出。我改为通过命令行构建,现在我可以看到 #21 [build 7/7] COPY [src/Shared Settings/, /app], #21 sha256:84551c91e9d61cab65cb11cfb976f1ef4a982ba9ad6ccee300062361b7142b52,
#21 ERROR: "/src/Shared Settings" not found: not found因此,它告诉我找不到Shared Settings文件夹。但是,我可以在docker容器的CLI中手动导航到它,并手动将文件从Shared Settings复制到/app。所以我不明白为什么构建不能这样做。
- DaveDev
...然后在这些消息之后,出现了无法计算缓存键:“/共享设置”未找到:未找到的错误。 - DaveDev
对于问题:“您要添加的目录是否是包含Dockerfile的目录的子目录?”我的回答是否定的——Shared Settings目录与包含dockerfile的目录处于同一级别。这意味着我应该引用父目录,例如../SharedSettings,但仍然会出现“未找到”错误。 - DaveDev
1
您不能从构建上下文目录的父目录或同级目录中使用 COPY ../anywhere 命令。另请参阅 如何在 Docker 的构建上下文之外包含文件? - David Maze

0

COPY src/Shared\ Settings /app 命令会失败,因为它是用于从构建上下文(包含 Dockerfile 的文件夹)复制的。然而,路径 '/src/Shared Settings' 表明您正在从主机的根目录构建。如果该 src 目录不在根目录 / 下,而是存在于另一个文件夹中(例如 /path/to/your/folder_containing_src_and_Dockerfile/src),则应更改 Dockerfile 中的指令为:

COPY 'src/Shared Settings' /app

这将删除在路径中引起命令混乱的前导/

编辑:如果您正在从src目录构建,请在Dockerfile中使用以下指令:

COPY 'Shared Settings' /app

嗨,谢谢您的回复,但我认为它还不太正确。使用单引号(如上所示):failed to create LLB definition: failed to process "'Shared": unexpected end of statement while looking for matching single-quote,使用双引号:failed to create LLB definition: failed to process "\"Shared"。没有引号(例如 COPY Shared\ Settings /app):failed to compute cache key: "/Shared" not found: not found - DaveDev
嗯,@David Maze 的语法对第二个命令有效吗?例如:COPY ["Shared Settings", "/app"] - pcamach2

0

COPY指令与您构建此镜像的上下文紧密相关。

实际上,文档中已经指出:

docker build命令从Dockerfile和“上下文”构建Docker镜像。构建的上下文是位于指定的PATHURL中的文件集。构建过程可以引用上下文中的任何文件。例如,您的构建可以使用COPY指令来引用上下文中的文件。

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

尽管如此,我们通常会这样做:

docker build .

你必须明白,这个最后的点 . ,你肯定在某些情况下忘记提供它时,Docker会抱怨它,实际上是构建发生的实际上下文。

你不必强制使用 . ——也就是当前目录——作为你的上下文。

因此,你需要提供正确的上下文,这将是一个文件夹,它将是/src/Shared Settings和包含你的Dockerfile的文件夹之间的共同祖先。

你可能会遇到一个大问题,因为 Shared Settings 文件夹只存在于 src 中,所以你能找到的唯一共同祖先可能会迫使你使用/作为你的上下文,从而使你的上下文变得非常庞大,构建时间也会变得很长。

为了解决这个问题,你可以使用.dockerignore文件来忽略所有无关的文件夹,只使用你想要使用的那个文件夹,即/src/Shared Settings和包含你的Dockerfile的文件夹。

另外,当你改变你的上下文时,请注意你需要调整这行代码:

COPY . .

现在将会显示:

COPY name_of_the_folder_containing_the_Dockerfile .

这里是一个示例,您需要根据实际文件夹层次结构进行调整。

这里是文件夹层次结构:

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

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"]

这是文件.dockerignore如何从上下文中排除文件夹unrelated的内容:
**
!src/docker
!src/shared_settings

现在,我可以进入文件夹src/docker并使用以下命令进行构建:

docker build -f Dockerfile ../..

或者进入文件夹 / 并使用以下命令进行构建

docker build -f src/docker/Dockerfile .

唯一重要的是包含 Dockerfile 的文件夹和文件夹shared_settings 都应该是我的上下文的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接