使用 Dockerfile 中唯一的 COPY 语句将一些文件和整个文件夹从主机复制到容器中?



我正在运行一个带有两个 COPY 语句的 Dockerfile:

WORKDIR /app
COPY requirements.txt entrypoint.sh ./
COPY binaries/ ./binaries

它工作正常,我最终得到了我需要的东西:

root:/# ls /app
requirements.txt
entrypoint.sh
binaries/
├── executable1
├── executable2
└── executable3

但我想保持尽可能少的层数,因此我尝试将两个 COPY 语句合并为一个:

WORKDIR /app
COPY requirements.txt entrypoint.sh binaries/ ./

但这是从binaries/文件夹中"提取"所有文件,并将它们放在其他两个文件旁边:

root:/# ls /app
requirements.txt
entrypoint.sh
executable1
executable2
executable3

问题

如何将某些文件一个或多个(或多个)特定文件夹合并为 Dockerfile 中的一个唯一 COPY 语句(当然,如果可能的话)?

环境信息:

Docker version 20.10.0, build 7287ab3    
Host: ubuntu 18.04.5

测试兆威

localhost:~$

mkdir -p doc && cd doc && mkdir -p binaries && touch entrypoint.sh 
requirements.txt binaries/ex1 binaries/ex2 binaries/ex3 
&& echo 'FROM debian:buster-slim
WORKDIR /app
COPY requirements.txt entrypoint.sh binaries ./' >> Dockerfile

localhost:~$

docker build --no-cache -t test:latest . 
&& docker run -it --rm --name test test:latest bash 

从容器内部:

root:/app# ls

给我:

entrypoint.sh  ex1  ex2  ex3  requirements.txt

使用ADD而不是COPY时会遇到相同的行为。

您可以在 Dockerfile 旁边创建一个具有以下结构的文件夹然后将内容复制到您的 apps 目录中,

$ tree
.
├── Dockerfile
└── folder
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── entrypoint.sh
└── requirements.txt
2 directories, 6 files

Dockerfile,

FROM debian:buster-slim
WORKDIR /app
COPY folder .
<小时 />
root@b111e73a17c1:/app# tree
.
|-- binaries
|   |-- executable1
|   |-- executable2
|   `-- executable3
|-- entrypoint.sh
`-- requirements.txt
1 directory, 5 files

如果不指定目标目录,您将无法COPYADD目录,如文档所示:

  • 如果<src>是目录,则会复制目录的全部内容,包括文件系统元数据。

注意

目录本身不会被复制,只会复制其内容。

来源:https://docs.docker.com/engine/reference/builder/#add https://docs.docker.com/engine/reference/builder/#copy

但是这里有两种可能性,因为 docker 不会递归地进入您的文件夹,您可以更改主机上的文件结构并执行以下操作:

.
└── to_mount
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── entrypoint.sh
└── requirements.txt

然后简单地:

COPY to_mount .

您可以使用另一种方式,这总是很高兴知道的,但根据您的用例可能会证明是非常不切实际的,那就是使用.dockerignore文件。

在 docker CLI 将上下文发送到 docker 守护程序之前,它会在上下文的根目录中查找名为.dockerignore的文件。如果此文件存在,CLI 将修改上下文以排除与其中的模式匹配的文件和目录。这有助于避免不必要地将大型或敏感文件和目录发送到守护程序,并可能使用ADDCOPY将它们添加到映像中。

来源: https://docs.docker.com/engine/reference/builder/#dockerignore-file

有了这个,您可以复制.然后添加.docker忽略当前主机文件夹中但您不想在映像中复制的其他文件。

这是我的码头工人文件夹

.
├── .dockerignore
├── Dockerfile
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── docker-compose.yml
├── entrypoint.sh
└── requirements.txt

.dockerignore包含

Dockerfile
docker-compose.yml
.dockerignore

所以,做:

COPY . .

我最终得到

.
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── entrypoint.sh
└── requirements.txt

使用Dockerfile

FROM alpine
RUN apk add --no-cache tree
WORKDIR /tmp
COPY . .

我们得到

$ tree -a
.
├── .dockerignore
├── Dockerfile
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── docker-compose.yml
├── entrypoint.sh
└── requirements.txt
1 directory, 8 files
$ docker run --rm -ti $(docker build -q .) tree -a
.
├── binaries
│   ├── executable1
│   ├── executable2
│   └── executable3
├── entrypoint.sh
└── requirements.txt
1 directory, 5 files

最新更新