如何在Docker文件中使用“ADD”命令包含Docker构建上下文之外的文件?

从Docker文档中:

路径必须位于生成的上下文中;您不能添加../something/something,因为docker构建的第一步是将上下文目录(和子目录)发送到docker守护进程。

我不想重组我的整个项目,只是为了在这件事上适应Docker。我想将所有Docker文件保存在同一个子目录中。

此外,Docker似乎还不支持符号链接:Dockerfile ADD命令不支持主机#1676上的符号链接。

我唯一能想到的另一件事是包含一个预构建步骤,将文件复制到Docker构建上下文中(并配置我的版本控制以忽略这些文件)。还有比这更好的解决方法吗?


当前回答

您还可以创建图像首先需要的内容的tarball,并将其用作上下文。

https://docs.docker.com/engine/reference/commandline/build/#/tarball-上下文

其他回答

正如GitHub问题中所描述的那样,构建实际上发生在/tmp/docker-12345中,因此相对路径如/相对添加/some文件是相对于/tmp/docker-12345的。因此,它将搜索/tmp/relative add/some文件,该文件也显示在错误消息中*

不允许包含来自构建目录之外的文件,因此这将导致“禁止路径”消息。"

在我的例子中,Dockerfile就像一个包含占位符的模板一样编写,我使用配置文件将其替换为实际值。

所以我不能直接指定这个文件,而是像这样将其导入docker构建:

sed "s/%email_address%/$EMAIL_ADDRESS/;" ./Dockerfile | docker build -t katzda/bookings:latest . -f -;

但由于管道的原因,COPY命令无法工作。但上述方法通过-f(明确表示未提供文件)来解决问题。只执行-如果不使用-f标志,则不会提供上下文和Dockerfile,这是一个警告。

我经常发现自己为此使用--buildarg选项。例如,在Dockerfile中放入以下内容后:

ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa

你可以这样做:

docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .

但请注意Docker文档中的以下警告:

警告:不建议使用构建时间变量来传递密钥,如github密钥、用户凭据等。使用docker history命令,映像的任何用户都可以看到构建时间变量值。

创建一个包装docker构建shell脚本,该脚本获取文件,然后调用docker构建,然后删除文件。

在我的快速浏览中,这里没有提到一个简单的解决方案:

有一个名为docker_build.sh的包装脚本让它创建tarball,将大文件复制到当前工作目录调用docker构建清理油布球、大文件等

这个解决方案很好,因为(1.)它没有复制SSH私钥的安全漏洞(2.)另一个解决方案使用sudo绑定,所以它有另一个安全漏洞,因为它需要root权限才能进行绑定。

一种快速而肮脏的方法是将构建上下文设置为所需的多个级别,但这可能会产生后果。如果您使用的是这样的微服务架构:

./Code/Repo1
./Code/Repo2
...

您可以将构建上下文设置为父代码目录,然后访问所有内容,但事实证明,对于大量存储库,这可能会导致构建花费很长时间。

示例情况可能是另一个团队在Repo1中维护数据库模式,而您的团队在Repo2中的代码依赖于此。您希望在不担心模式更改或污染其他团队的存储库的情况下,将这种依赖关系与您自己的种子数据固定在一起(当然,根据更改的内容,您可能仍然需要更改种子数据脚本)第二种方法很粗糙,但避开了长构建的问题:

在中创建sh(或ps1)脚本/Code/Rep2复制所需文件并调用所需的docker命令,例如:

#!/bin/bash
rm -r ./db/schema
mkdir ./db/schema

cp  -r ../Repo1/db/schema ./db/schema

docker-compose -f docker-compose.yml down
docker container prune -f
docker-compose -f docker-compose.yml up --build

在docker compose文件中,只需将上下文设置为Repo2根目录并使用的内容/dockerfile中的db/schema目录,而不必担心路径。请记住,您可能会意外地将此目录提交给源代码管理,但脚本清理操作应该足够简单。