Dockerfile复制保留子目录结构

533

我试图将一些文件和文件夹从本地主机复制到一个Docker镜像构建中。

这些文件像这样:

folder1/
    file1
    file2
folder2/
    file1
    file2

我想让文本看起来像这样:

COPY files/* /files/

然而,所有来自folder1/folder2/的文件都直接放在/files/文件夹中,而不是它们原来的文件夹中:

files/
    file1
    file2

在Docker中有没有一种方法可以保留子目录结构,并将文件复制到它们所在的目录中?像这样:

files/
    folder1/
        file1
        file2
    folder2/
        file1
        file2

4
你能否澄清一下你得到了什么结果以及你期望得到什么结果? - Thomasleveil
3
我同意,@Thomasleveil。答案很清楚,但问题不明确。 - Mike Williamson
@Thomasleveil,看起来他们想要保留目录,但星号会使Docker复制目录的内部而不是目录本身。 - Artfaith
5个回答

723

使用这个 Dockerfile 移除 COPY 中的星号:

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

结构已经存在:

$ 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

134
如果我只需要一些文件,比如 COPY files/*1 /files/,该怎么办?请帮我翻译。 - Pavel Agarkov
3
这会覆盖该目录中现有的文件吗? - chander
3
@chander,是的,现有文件将被覆盖。 - ISanych
15
值得注意的是,这里的关键在于只有一个源目录和一个目标目录被指定。任何其他组合都会将源目录(们)的内容复制到目标目录中。 - Marcin
2
这对我在macOS上使用ibmcom/websphere-liberty:kernel-java8-ibmjava-ubi构建时没有起作用。尽管这篇文章中的其他解决方案也没有起作用。 - Georgios F.
显示剩余3条评论

90

要将本地目录合并到镜像中的目录中,请执行以下操作。它不会删除已经存在于镜像中的文件。它只会添加本地存在的文件,如果同名文件已经存在,则会覆盖镜像中的文件。

COPY ./local-path/. /image-path/

1
这是最佳解决方案,因为您可以使用一个命令将整个文件系统的更改复制到映像层中。我在源代码库中保留了一个/resources目录,以镜像要添加/覆盖的映像文件系统的部分。然后只需一次性添加所有内容:COPY resources/./ / - ryanhos

89

你也可以使用 "." 代替 *,这将获取工作目录中的所有文件,包括文件夹和子文件夹:

FROM ubuntu
COPY . /
RUN ls -la /

2
这将包括像'.git'目录这样的隐藏文件和目录吗? - Bruno Negrão Zica
20
@BrunoNegrãoZica,您可以使用.dockerignore文件来指定在复制操作期间希望忽略的文件/文件夹。虽然现在有点晚了,但希望能对其他人有所帮助。 - Hellaren
8
在Docker Desktop 4.0.1中,COPY . ./对我有用,而COPY . /则不行。 - smoq
1
使用 ".dockerfile": WORKDIR /usr/src/app COPY . . - Kevin
1
@smoq:这是两个不同的语句,可能都有效,但只有一个符合您的预期。第一个将文件复制到容器中的CWD,第二个将它们复制到容器中的根目录。 - 7yl4r

12

我试了以上所有解答都无法解决我的问题。我必须加一个点来表示当前目录,所以有效的Docker文件看起来如下:

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

另外,对我来说使用RUN ls进行验证并不起作用,使它起作用看起来非常复杂。验证 Docker 文件中的内容更简单的方法是运行交互式 shell,并检查其中的内容,使用docker run -it <tagname> sh


6
如果你想完整复制一个源目录并保持相同的目录结构,那么不要使用星号(*)。在Dockerfile中编写COPY命令如下。
COPY . destinatio-directory/ 

3
OP特别询问的是当前目录中的一个目录,而不是当前目录的内容。COPY files/ /files/没有通配符就是答案。 - TheZeke
TheZeke提醒我们要注意某些事情。然而,这也是一个很好的提醒,告诉我们将上下文复制到例如/var/www/html目标的简单性。 - Gustavo Pinsard

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