如何在 Docker 的构建上下文之外包含文件?

How to include files outside of Docker's build context?

提问人:ben_frankly 提问时间:11/22/2014 最后编辑:tshepangben_frankly 更新时间:11/15/2023 访问量:525229

问:

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

在 Docker 文档中:

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

我不想仅仅为了适应Docker而重组我的整个项目。我想将我所有的Docker文件保存在同一个子目录中。

此外,Docker 似乎还没有(也可能永远不会)支持符号链接:Dockerfile ADD 命令不遵循主机 #1676 上的符号链接。

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

码头工人

评论

294赞 TigerBear 1/16/2018
这一定是 Docker 最糟糕的事情。在我看来,没有“Docker项目”这样的东西。Docker 用于交付项目。它只是一个工具。我不想重建我的整个项目来适应 docker,添加 .dockerignore 等。归根结底,谁知道 Docker 会持续多久?在代码(即 angular 项目)和部署它的任何方式(即 docker)之间进行分离会很棒。毕竟,在其他所有内容旁边都有一个 docker 文件确实没有任何好处。它只是连接东西以创建一个图像:(
15赞 jersey bean 3/23/2018
是的,这是一个很大的挫折。我面临同样的问题,我有一个更大尺寸的二进制文件(已经压缩),我不想将其复制到每个 Docker 构建上下文中。我宁愿从其当前位置(在 Docker 构建上下文之外)获取它。而且我不想在运行时映射卷,因为我正在尝试在构建时复制/添加文件并解压缩并执行我需要的操作,以便将某些二进制文件烘焙到映像中。这样可以快速旋转容器。
0赞 Marcello DeSales 11/14/2018
我找到了一个很好的结构,我在 stackoverflow.com/a/53298446/433814 上详细解释
10赞 Devis L. 5/4/2019
Docker 构建的问题在于“上下文”的虚构概念。Dockerfile 不足以定义构建,除非它们被放置在战略目录(又名上下文)下,即“/”作为极端,因此您可以访问任何路径(请注意,这在理智的项目中也不是正确的做法......,而且它使 docker 构建非常慢,因为 docker 在开始时会扫描整个上下文)。您可以考虑使用所有必需的文件构建一个 docker 映像,然后从那里继续。我不会更改项目结构以适应 Docker(或任何构建工具)。FROM
3赞 Sami Wood 10/25/2022
在新功能中,如果您有 dockerfile 1.4+ 和 buildx 0.8+,您可以执行如下操作,请参阅下面的答案docker buildx build --build-context othersource= ../something/something .

答:

23赞 Usman Ismail 11/22/2014 #1

如果您阅读了问题 2745 中的讨论,不仅 docker 可能永远不支持符号链接,而且可能永远不支持在您的上下文之外添加文件。似乎是一种设计理念,即进入 docker build 的文件应该明确地成为其上下文的一部分,或者来自一个 URL,它可能也部署了一个固定版本,以便构建可以使用众所周知的 URL 或 docker 容器附带的文件重复。

我更喜欢从版本控制的源代码构建 - 即docker build -t stuff http://my.git.org/repo - 否则我正在使用随机文件从某个随机位置构建。

从根本上说,没有.... -- SvenDowideit,Docker Inc

只是我的意见,但我认为你应该重组以分离代码和 docker 存储库。这样,容器可以是通用的,并在运行时(而不是在构建时)拉入任何版本的代码。

或者,使用 docker 作为基本代码部署项目,然后将 dockerfile 放在代码存储库的根目录中。如果您采用此路线,则使用父 Docker 容器(用于更常规的系统级别详细信息)和子容器(用于特定于代码的设置)可能是有意义的。

评论

9赞 lscoughlin 6/2/2020
那为什么要使用 docker 呢?
59赞 Günter Zöchbauer 11/22/2014 #2

在 Linux 上,您可以挂载其他目录,而不是对它们进行符号链接

mount --bind olddir newdir

有关详细信息,请参阅 https://superuser.com/questions/842642

我不知道其他操作系统是否有类似的东西可用。 我还尝试使用 Samba 共享一个文件夹并将其重新挂载到 Docker 上下文中,这也有效。

评论

7赞 jjcf89 6/13/2019
只有 root 才能绑定目录
0赞 SOFe 3/16/2021
无论如何,可以访问 docker 的用户都有某种 root 访问权限,因为可以使用任意 docker 命令来破坏 chroot jail(或者只是将所需的文件挂载到容器中)
696赞 Cyberwiz 12/21/2015 #3

解决此问题的最佳方法是使用 -f 独立于生成上下文指定 Dockerfile。

例如,此命令将授予 ADD 命令访问当前目录中任何内容的权限。

docker build -f docker-files/Dockerfile .

更新:Docker 现在允许将 Dockerfile 置于构建上下文之外(已在 18.03.0-ce 中修复)。所以你也可以做类似的事情

docker build -f ../Dockerfile .

评论

13赞 Emerson Farrugia 7/9/2016
@Ro,您可以在 Compose 文件 docs.docker.com/compose/compose-file/#/compose-file-reference 的部分中使用该属性dockerfile:build:
121赞 Sridhar Sarnobat 9/19/2017
这是否解决了 OP 想要上下文目录之外的文件的问题?这就是我要做的,但我不认为使用会使外部文件可添加。ADD-f
13赞 jersey bean 3/23/2018
如果您尝试从 Docker 构建上下文之外的完全不同的文件获取文件,则此解决方案确实没有用处。即假设您的文件位于 /src/my_large_file.zip 下,而您的 Docker 构建上下文位于 /home/user1/mydocker_project 下。我不想将文件复制到 Docker 构建上下文,因为它很大,我想将其一些内容烘焙到映像中,以便启动容器的过程不会很慢。
43赞 Mike Gleason jr Couturier 7/12/2018
对此赞不绝口。.在我的docker-compose.yml我有: .现在我的构建上下文是父目录!build: context: .., dockerfile: dir/Dockerfile
13赞 oarfish 8/14/2019
我从包含大量文件的目录运行它,结果是我正在查看一条消息,它似乎复制了千兆字节的数据。sending build context to Docker deamon
14赞 Laurent Picquet 9/12/2016 #4

您还可以创建图像首先需要的压缩包,并将其用作上下文。

https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts

评论

5赞 Tore Olsen 5/9/2020
很棒的提示!我发现您甚至可以将 docker 构建 tarball 作为 stdin 的上下文:。这对我的情况非常有帮助。tar zc /dir1 /dir2 |docker build -
0赞 ceztko 2/16/2022
也可以从本地现有的 tar 中获取,请参阅答案
23赞 Anshuman Manral 9/13/2017 #5

我相信更简单的解决方法是更改“上下文”本身。

因此,例如,与其给予:

docker build -t hello-demo-app .

它将当前目录设置为上下文,假设您希望父目录作为上下文,只需使用:

docker build -t hello-demo-app ..

评论

10赞 NullVoxPopuli 3/10/2018
我认为这打破了.dockerignore :-\
1赞 11/26/2019
我放弃了 .dockerignore,而是制作了 Makefile 托管的 docker 文件夹,该文件夹仅包含构建上下文所需的文件......我只需要调用它,如果它们已更新,它会拉入所需的所有文件,然后调用适当的 docker build...我需要做额外的工作,但它可以完美运行,因为我完全可以控制。make build
1赞 cowlinator 7/11/2023
.dockerignore必须位于上下文的根目录中。如果将上下文从 更改为 ,则必须将文件向上移动一个目录。....dockerignore
83赞 aaron 11/29/2017 #6

我经常发现自己将该选项用于此目的。例如,在将以下内容放入 Dockerfile 后:--build-arg

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 命令,映像的任何用户都可以看到构建时变量值。

评论

21赞 sheldonh 1/17/2019
这是一个糟糕的建议,没有太大的警告。来自 Docker 文档:“警告:不建议使用构建时变量来传递 github 密钥、用户凭据等机密。使用 docker history 命令对映像的任何用户都可以看到构建时变量值。[1] 换句话说,此示例中给出的示例公开了 docker 映像中的 SSH 私钥。在某些情况下,这可能没问题。docs.docker.com/engine/reference/builder/#arg
5赞 Jojo 8/15/2019
最后,为了克服这个安全问题,你可以使用压缩或多阶段构建等技术: vsupalov.com/build-docker-image-clone-private-repo-ssh-key
0赞 Josh 9/27/2023
这与 OP 正在寻找的有所不同。您只是在本地环境中执行 cat 并将结果传递给 。这不是 docker 本身引用上下文区域之外的密钥文件(OP 的问题)。docker build
93赞 Marcello DeSales 11/14/2018 #7

我花了很长时间试图找出一个好的模式,以及如何更好地解释此功能支持发生了什么。我意识到最好的解释方式如下......

  • Dockerfile:只能看到其自身相对路径下的文件
  • 上下文:在“空间”中要共享的文件和 Dockerfile 将被复制到的位置

因此,话虽如此,这里有一个 Dockerfile 示例,它需要重用一个名为start.sh

Docker文件

它将始终从其相对路径加载,并将自身的当前目录作为对指定路径的本地引用。

COPY start.sh /runtime/start.sh

文件

考虑到这个想法,我们可以考虑为 Dockerfile 构建特定的东西提供多个副本,但它们都需要访问 .start.sh

./all-services/
   /start.sh
   /service-X/Dockerfile
   /service-Y/Dockerfile
   /service-Z/Dockerfile
./docker-compose.yaml

考虑到这种结构和上面的文件,这里有一个docker-compose.yml

docker-compose.yaml

  • 在此示例中,共享上下文目录是运行时目录。
    • 同样的心智模型在这里,认为这个目录下的所有文件都被移到了所谓的上下文中。
    • 同样,只需指定要复制到同一目录的 Dockerfile。您可以使用 .dockerfile
  • 主要内容所在的目录是要设置的实际上下文。

具体如下docker-compose.yml

version: "3.3"
services:
  
  service-A
    build:
      context: ./all-service
      dockerfile: ./service-A/Dockerfile

  service-B
    build:
      context: ./all-service
      dockerfile: ./service-B/Dockerfile

  service-C
    build:
      context: ./all-service
      dockerfile: ./service-C/Dockerfile
  • all-service设置为上下文,则共享文件以及每个 .start.shdockerfile
  • 每个人都可以以自己的方式构建,共享启动文件!

评论

8赞 β.εηοιτ.βε 2/21/2019
正如公认的答案所指出的那样,您在 Dockerfile 上的观点并不完全正确,如果您在文件夹层次结构中,那么是的,运行 in 将不允许您访问 .但是,我认为这(或至少我的)普遍误解是上下文是由构建命令的第一个参数声明的位置定义的,而不是由 Dockerfile 的位置定义的。因此,正如公认的答案中所述: from : 表示 Dockerfile 中现在是文件夹a/b/cdocker build .c../file-in-badocker build -f a/b/c/Dockerfile . .a
4赞 Nishant George Agrwal 12/18/2019
引用 Dockerfile 文档:文件和目录的路径将被解释为相对于构建上下文的源。
0赞 Robert Sinclair 2/12/2021
衷心感谢您仔细记录这一点,真的很有帮助。
1赞 Marcello DeSales 2/12/2021
@RobertSinclair,不是问题哥们!这在开发过程中对我有很大帮助......我很高兴它有所帮助!!
0赞 Pini Cheyni 3/7/2021
这应该是针对此问题的选择解决方案,我从未在 docker build 中使用过上下文,但现在没有它我就无法工作!这是最优雅、最有用的解决方案
1赞 Annulet Consulting 11/30/2018 #8

我有一个项目和一些数据文件遇到了同样的问题,由于 HIPAA 原因,我无法在存储库上下文中移动。我最终使用了 2 个 Dockerfile。一个在没有容器外部需要的东西的情况下构建主应用程序,并将其发布到内部存储库。然后,第二个 dockerfile 拉取该映像并添加数据并创建一个新映像,然后部署该映像,并且永远不会存储在任何地方。不理想,但它适用于我将敏感信息排除在存储库之外的目的。

5赞 Kris Rivera 1/31/2019 #9

使用 docker-compose,我通过创建一个服务来装载我需要的卷并提交容器的映像来实现这一点。然后,在后续服务中,我依赖于先前提交的映像,该映像将所有数据存储在装载位置。然后,您必须将这些文件复制到其最终目标,因为在运行命令时不会提交主机挂载目录docker commit

您不必使用 docker-compose 来完成此操作,但它使生活更轻松一些

# docker-compose.yml

version: '3'
  services:
    stage:
      image: alpine
      volumes:
        - /host/machine/path:/tmp/container/path
      command: bash -c "cp -r /tmp/container/path /final/container/path"
    setup:
      image: stage
# setup.sh

# Start "stage" service
docker-compose up stage

# Commit changes to an image named "stage"
docker commit $(docker-compose ps -q stage) stage

# Start setup service off of stage image
docker-compose up setup

评论

0赞 MatTheCat 10/6/2023
使用 compose,您现在可以使用 定义多个上下文: github.com/compose-spec/compose-spec/pull/307build.additional_contexts
2赞 Ben Wex 10/24/2019 #10

一个简单的解决方法可能是在运行容器时简单地将卷(使用 -v 或 --mount 标志)挂载到容器中,并以这种方式访问文件。

例:

docker run -v /path/to/file/on/host:/desired/path/to/file/in/container/ image_name

有关更多信息,请参阅:https://docs.docker.com/storage/volumes/

评论

7赞 user3735633 2/18/2020
请注意,仅当卷是运行时依赖项时,这才有效。对于构建时依赖项,为时已晚。docker run
1赞 Dave 4/11/2023
此外,挂载卷会将文件复制到上下文中要挂载到的位置。这意味着它使我的文件翻倍。如果我需要挂载一个包含 100 个脚本的卷文件夹怎么办?现在我的主机的脚本数量增加了一倍。
0赞 user1007074 12/13/2019 #11

一种快速而肮脏的方法是根据需要设置尽可能多的级别 - 但这可能会产生后果。 如果你在如下所示的微服务体系结构中工作:

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

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

一个示例情况可能是,另一个团队维护一个数据库架构,而团队的代码依赖于此架构。您希望使用自己的一些种子数据对这种依赖项进行 docker 化,而不必担心架构更改或污染其他团队的存储库(当然,根据更改的内容,您可能仍然需要更改种子数据脚本) 第二种方法是 hacky,但可以解决长构建的问题:Repo1Repo2

创建一个 sh(或 ps1)脚本来复制所需的文件并调用所需的 docker 命令,例如:./Code/Repo2

#!/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 文件中,只需将上下文设置为 root 并使用 dockerfile 中的目录内容,而无需担心路径。 请记住,您将冒着意外将此目录提交到源代码管理的风险,但脚本清理操作应该足够简单。Repo2./db/schema

1赞 Daniel Katz 1/20/2020 #12

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

所以我不能直接指定这个文件,而是像这样将其管道输送到 docker 构建中:

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

但是由于管道的原因,该命令不起作用。但是上述方法通过(明确说明未提供文件)来解决它。仅不使用标志,则不提供上下文和 Dockerfile,这是一个警告。COPY-f ---f

评论

2赞 nadavvadan 1/4/2021
仅供参考,您可以使用build-args
0赞 Christopher Thomas 12/8/2021
该解决方案建议使用 “docker build -t <tag> 。-f -“还解决了我想通过 bash 脚本生成 dockerfile 并通过 STDIN 输入的问题,但我也想从本地上下文中复制文件”。
5赞 Rocksn17 2/9/2020 #13

正如 GitHub 问题中所述,构建实际上发生在 中,因此相对路径 like 是相对于 的。因此,它将搜索 ,这也显示在错误消息中。/tmp/docker-12345../relative-add/some-file/tmp/docker-12345/tmp/relative-add/some-file

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

3赞 fde-capu 12/23/2020 #14

使用链接的解决方法:

ln path/to/file/outside/context/file_to_copy ./file_to_copy

在 Dockerfile 上,只需:

COPY file_to_copy /path/to/file

评论

1赞 Greg 1/16/2021
我可能不会使用它,因为这不适用于软链接,仅适用于硬链接
0赞 Sherif eldeeb 4/21/2021
未知指令:LN
0赞 fde-capu 4/22/2021
@Sheldeeb将在 Unix 上下文中使用,而不是在 Dockerfile 中使用,以创建硬链接(参见 en.wikipedia.org/wiki/Ln_(Unix))。然后将链接视为常规文件。它不是大写的“LN”。ln
0赞 Sherif eldeeb 4/23/2021
这可能会影响代码库,即:覆盖现有文件,甚至修改干净的 Git 存储库。此外,您可能无法重命名文件,例如,如果您想在创建硬链接后运行,则无法修改package.jsonnpm install
0赞 Gordon Tytler 11/22/2023
当尝试递归复制带有软链接的目录时......你猜怎么着?没有复制任何内容。但是你看,即使我们找到了一种方法将大量数据复制到图像中,这仍然是一个问题。构建需要很长时间,最终会得到巨大的图像文件。我现在放弃了,只是将其全部复制到构建上下文中,所以我仍然会有这些延迟。我不想要一个全新的容器和通信,只用于仅加载到内存中的数据。
5赞 Trevor Boyd Smith 3/24/2021 #15

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

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

  • 有一个名为docker_build.sh
  • 让它创建压缩包,将大文件复制到当前工作目录
  • docker build
  • 清理压缩包、大文件等

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

1赞 jrasm91 4/2/2021 #16

如何在两个 Dockerfile 之间共享打字稿代码

我遇到了同样的问题,但是在两个打字稿项目之间共享文件。其他一些答案对我不起作用,因为我需要保留共享代码之间的相对导入路径。我通过这样组织我的代码来解决它:

api/
  Dockerfile
  src/
    models/
      index.ts

frontend/
  Dockerfile
  src/
    models/
      index.ts

shared/
  model1.ts
  model2.ts
  index.ts

.dockerignore

注意:将共享代码提取到该顶部文件夹后,我避免了需要更新导入路径,因为我更新了并从共享中导出:(例如api/models/index.tsfrontend/models/index.tsexport * from '../../../shared)

由于构建上下文现在高出一个目录,因此我必须进行一些额外的更改:

  1. 更新 build 命令以使用新上下文:

    docker build -f Dockerfile ..(两个点而不是一个点)

  2. 顶层使用单个来排除所有 .(例如.dockerignorenode_modules**/node_modules/**)

  3. 在命令前面加上 或DockerfileCOPYapi/frontend/

  4. 复制(除了 或sharedapi/srcfrontend/src)

    WORKDIR /usr/src/app
    
    COPY api/package*.json ./     <---- Prefix with api/
    RUN npm ci
    
    COPY api/src api/ts*.json ./  <---- Prefix with api/
    COPY shared usr/src/shared    <---- ADDED
    RUN npm run build
    

这是我可以将所有内容发送到 docker 的最简单方法,同时保留两个项目中的相对导入路径。棘手(烦人)的部分是由于构建上下文位于一个目录上而引起的所有更改/后果。

4赞 Seyed Mostafa SeyedAshoor 9/29/2021 #17

我个人对一些答案感到困惑,所以决定简单地解释一下。

在以下情况下,应将 Dockerfile 中指定的上下文传递给 docker 想要创建图像。

我总是选择项目的根目录作为 Dockerfile 中的上下文

因此,例如,如果您使用 COPY 命令,例如 COPY .

第一个 dot(.) 是上下文,第二个 dot(.) 是容器工作目录

假设上下文是项目根目录,dot(.) ,代码结构如下所示

sample-project/
  docker/
    Dockerfile

如果要构建映像

您的路径(运行 docker build 命令的路径)是 /full-path/sample-project/, 你应该这样做

docker build -f docker/Dockerfile . 

如果您的路径是 /full-path/sample-project/docker/, 你应该这样做

docker build -f Dockerfile ../ 
14赞 isca 2/8/2022 #18

此行为由 or 用于将文件呈现给生成过程的上下文目录提供。
一个很好的技巧是在构建指令期间将上下文目录更改为要公开给守护程序的目录的完整路径。 例如:
dockerpodman

docker build -t imageName:tag -f /path/to/the/Dockerfile /mysrc/path

使用 而不是 (当前目录),您将使用该目录作为上下文,因此构建过程可以看到该目录下的任何文件。
在此示例中,您将向 docker 守护程序公开整个树。
当与触发构建的用户 ID 一起使用时,必须对上下文目录中的任何单个目录或文件具有递归读取权限
/mysrc/path./mysrc/pathdocker

如果你拥有但想要将不在同一目录中的文件引入此容器生成上下文,这可能很有用。/home/user/myCoolProject/Dockerfile

下面是使用 context dir 构建的示例,但这次使用 而不是 .podmandocker

让我们举个例子,在你的 a 或指令中,它从项目外部的目录复制文件,例如:DockerfileCOPYADD

FROM myImage:tag
...
...
COPY /opt/externalFile ./
ADD /home/user/AnotherProject/anotherExternalFile ./
...

为了构建它,使用位于 的容器文件,只需执行以下操作:/home/user/myCoolProject/Dockerfile

cd /home/user/myCoolProject
podman build -t imageName:tag -f Dockefile /

更改上下文目录的一些已知用例是使用容器作为工具链来构建源代码时。
例如:

podman build --platform linux/s390x -t myimage:mytag -f ./Dockerfile /tmp/mysrc

或者它可以是相对路径,例如:

podman build --platform linux/s390x -t myimage:mytag -f ./Dockerfile ../../

这次使用全局路径的另一个示例:

FROM myImage:tag
...
...
COPY externalFile ./
ADD  AnotherProject ./
...

请注意,现在 Dockerfile 命令层中省略了 COPY 和 ADD 的完整全局路径。
在这种情况下,必须相对于文件所在的位置,如果两者都在目录中,则用于构建它必须是:
contex direxternalFileAnotherProject/optcontext dir

podman build -t imageName:tag -f ./Dockerfile /opt

请注意,在 docker 中将 COPYADD 与上下文目录一起使用时
守护程序将尝试将上下文目录树上可见的所有文件“流式传输”到守护程序,这可能会减慢构建速度。并要求用户具有来自上下文目录的递归权限。 这种行为可能会更昂贵,尤其是在通过 API 使用构建时。但是,构建是即时发生的,不需要递归权限,这是因为它没有枚举整个上下文目录,也没有使用架构。
当您使用不同的上下文目录遇到此类问题时,使用此类情况的构建可能更有趣,而不是 。
dockerpodmanpodmanclient/serverpodmandocker

一些参考资料:

评论

2赞 Alex Povel 2/18/2022
这是危险的,也是不可取的。Docker 生成上下文将是整个计算机。首先,将整个上下文发送到守护程序将花费很长时间。其次,构建过程本身可以做任何它真正想做的事情。恶意 Dockerfile 可以连接到具有完全文件系统读取访问权限的远程服务器。最后,你的 Dockerfile 指令会与你的机器紧密耦合,需要所有内容的完整路径,也就是绝对路径。它们将不再便携。ADD
0赞 isca 3/4/2022
这里的重点是解释切入点及其工作原理,而不是判断最佳标准。请记住,最好的办法是将所有内容都独立保存在同一个项目中。但是,问题是如何实现这种行为并演示入口点的工作原理。它不会永远花费,因为守护程序中没有枚举来实现它。这里的上下文在构建中是由具有权限的 ID 定义的,而不是由守护程序中的固定路径定义的,因此恶意 Dockefile 在这里没有意义。
0赞 Alex Povel 3/4/2022
你测试了你的答案的片段吗?作为普通用户,假设使用 Unix 操作系统,您甚至没有对所有 .它只会在权限被拒绝的情况下出错。运行上述内容可以(?)修复它,但这是一个糟糕的主意。无论如何,在将 3GB 的构建上下文加载到守护程序的构建上下文中后,我 CTRL+C 退出了我运行的构建过程进行测试。以上对我根本不起作用!/root/
0赞 isca 3/7/2022
可以肯定的是,在这两种情况下,它都有效,这不是一个标准问题,而是上下文目录存在的原因问题。在这里,我以示例为例来说明它的曝光情况。但是,我改进了答案以解决您在这里的担忧/
0赞 Illegal Operator 6/29/2023
漂亮的技巧,只要你控制构建命令和docker文件,否则顽皮的开发人员可以从你的构建机器上删除任何文件:)
10赞 Sami Wood 10/25/2022 #19

我认为从今年早些时候开始,buildx 中添加了一个功能来做到这一点。

如果你有 dockerfile 1.4+ 和 buildx 0.8+,你可以做这样的事情:

docker buildx build --build-context othersource= ../something/something .

然后,在 docker 文件中,您可以使用 from 命令添加上下文

ADD –-from=othersource . /stuff

请参阅此相关帖子

评论

0赞 anatol 6/14/2023
这仅适用于目录吗?我无法传递文件路径并出现错误ERROR: failed to get build context path {/builds/my_file <nil>}: not a directory
0赞 MatTheCat 10/6/2023
我实际上来这里是为了提到多个构建上下文,很遗憾我不得不滚动这么久才能找到你的答案..!
1赞 123 4/14/2023 #20

更改生成上下文是要走的路。

如果有一个 .net core 项目,并且仍想使用 Visual Studio UI 通过 docker 调试/发布项目,则可以通过将“DockerfileContext”添加到项目 .csproj 来更改上下文:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
    <DockerfileContext>..\..\.</DockerfileContext>
  </PropertyGroup>

  ...

</Project>

不要忘记相应地更改 Dockerfile 中的路径。

2赞 Anatoly 11/15/2023 #21

我对这个问题的解决方法。寻找优雅的解决方案,每次构建映像时都不需要重新发明,并决定创建以下 build-docker.sh bash 脚本:

#!/bin/bash

# Check if a tag argument is provided
if [ "$#" -ne 1 ]; then
    echo "Usage: $0 <tag>"
    exit 1
fi

# Assign the tag argument to a variable
TAG=$1

# Copy the source-code directory
cp -R ../source-code ./temp-source-code

# Run the Docker build command with the specified tag
docker build -t "$TAG" .

# Check if Docker build was successful
if [ $? -eq 0 ]; then
    echo "Docker build successful, removing temp-source-code directory..."
    rm -rf ./temp-source-code
else
    echo "Docker build failed, temp-source-code directory not removed."
fi

在 Dockerfile 中:

# Copy the rest of your application's source code
COPY . .

# Remove the existing symlink
RUN rm -f ./src/source-code

# Copy lambda parser
COPY ./temp-source-code ./src/source-code

综上所述:

  1. 使用所需的图像标记运行脚本
  2. 它会将所需的文件夹复制到当前目录中
  3. 将运行docker build ...
  4. 将从当前控制器中删除复制的文件夹
  5. 在 Dockerfile 中,只需添加删除符号链接的行,否则您的文件夹将不会被复制
  6. 运行脚本,享受你的生活:)