来自Docker文档:
路径必须处于构建环境中;您不能添加
../something/something,因为docker构建的第一步是
将上下文目录(和子目录)发送到docker守护程序。
我不想为了适应Docker而重组我的整个项目。我想将所有Docker文件都保存在同一子目录中。
此外,看来Docker尚未(而且可能永远不会)支持符号链接:Dockerfile ADD命令未遵循主机上的符号链接# 1676。
我唯一想到的另一件事是包括一个预构建步骤,以将文件复制到Docker构建上下文中(并配置我的版本控件以忽略那些文件)。有没有比这更好的解决方法了?
#1 楼
解决此问题的最佳方法是使用-f指定与构建上下文无关的Dockerfile。例如,此命令将为ADD命令提供对当前目录中任何内容的访问权限。 />
docker build -f docker-files/Dockerfile .
更新:Docker现在允许将Dockerfile置于构建上下文之外(已在18.03.0-ce中修复,https://github.com/docker/cli/pull/ 886)。因此,您也可以执行类似的操作
docker build -f ../Dockerfile .
评论
@Ro。您在撰写文件docs.docker.com/compose/compose-file/#/compose-file-reference的build:部分中使用dockerfile:属性
–艾默生·法鲁吉亚(Emerson Farrugia)
16年7月9日在10:35
我得到“ Dockerfile必须在构建上下文中”-我真的很想拥有一个可以驻留在当前构建上下文之下的Dockerfile。在您的示例中,Dockerfile在当前构建上下文内/下方,这当然可以工作。
–亚历山大·米尔斯(Alexander Mills)
17年2月4日在9:38
这是否解决了OP想要添加上下文目录之外的文件的问题?这就是我要尝试的操作,但是我不认为使用-f可以使外部文件可添加。
– Sridhar Sarnobat
17年9月19日在2:25
无法对此进行足够的投票..在我的docker-compose.yml中,我具有:构建:上下文:..,dockerfile:dir / Dockerfile。现在,我的构建上下文是父目录!
–迈克·格里森(Mike Gleason)和小库图里(Courutier)
18年7月12日在12:49
我正在从包含大量文件的目录中运行此文件,结果是正在查看一条消息,该消息显示将构建上下文发送到Docker守护进程,并且似乎复制了千兆字节的数据。
– ar鱼
19年8月14日在9:40
#2 楼
我经常发现自己将--build-arg
选项用于此目的。例如,将以下内容放入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文档:“警告:不建议使用构建时变量来传递诸如github密钥,用户凭据等机密。构建时变量值对于使用docker history命令的映像的任何用户都是可见的。” [1]换句话说,此示例中给出的示例在docker映像中公开了私有SSH密钥。在某些情况下,这可能很好。 docs.docker.com/engine/reference/builder/#arg
–谢尔顿
19年1月16日在16:26
最后,要解决此安全问题,可以使用压扁或多阶段构建等技术:vsupalov.com/build-docker-image-clone-private-repo-ssh-key
– Jojo
19年8月15日在13:35
#3 楼
在Linux上,您可以挂载其他目录,而不用符号链接它们 mount --bind olddir newdir
请参见https:// superuser.com/questions/842642了解更多详细信息。
我不知道其他操作系统是否可以使用类似的软件。
我还尝试使用Samba共享文件夹并将其重新安装到效果很好的Docker上下文。
评论
只有root可以绑定目录
– jjcf89
19年6月13日在15:04
#4 楼
我花了很多时间试图找出一个好的模式,以及如何更好地解释此功能支持所发生的情况。我意识到,解释它的最好方法如下...Dockerfile:将仅在其相对路径下看到文件
上下文:在“空间”中您放置文件的位置想要共享,您的Dockerfile将被复制到
因此,这就是一个示例,该Dockerfile需要重用一个名为
start.sh
的文件,它将始终从其相对路径加载,将其自身的当前目录作为您指定路径的本地引用。
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
在此示例中,您的共享上下文目录是运行时目录。
这里的思维模型相同,请认为该目录下的所有文件都移至s类似地,只需指定要复制到该目录的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.sh
以及Dockerfile也被复制到那里由每个dockerfile
指定。每个都可以以自己的方式构建,共享启动文件!
评论
正如您接受的答案所指出的那样,您对Dockerfile的观点并不完全正确,如果您位于文件夹层次结构a / b / c中,则可以运行docker build。在C中不允许您访问../file-in-b。但是,我认为对此(或至少是我的)普遍的误解是,上下文是由build命令的第一个参数指定的位置而不是Dockerfile的位置定义的。因此,如接受的答案所述:来自a:docker build -f a / b / c / Dockerfile。意味着在Dockerfile中。现在是文件夹
–β.εηοιτ.βε
19年2月21日在10:26
引用Dockerfile文档:文件和目录的路径将被解释为相对于构建上下文源的相对路径。
– Nishant George Agrwal
19/12/18在8:59
#5 楼
如果您阅读问题2745中的讨论,不仅docker可能永远都不支持符号链接,他们可能永远也不支持在您的上下文之外添加文件。似乎是一种设计理念,进入docker build的文件应该明确地是其上下文的一部分,或者也应该来自URL(假定它也以固定版本进行部署),以便该构建可以与众所周知的URL或随Docker一起提供的文件重复进行。泊坞窗容器。我更喜欢从版本控制的源进行构建-即docker build
-t的东西http://my.git.org/repo-否则,我将从
从根本上说,不....-Docker Inc. SvenDowideit
我的看法是,但我认为您应该重组为分离出代码和docker存储库。这样,容器可以是通用的,并且可以在运行时而不是构建时引入任何版本的代码。
或者,将docker用作您的基本代码部署工件,然后将dockerfile放入代码存储库的根目录中。如果您采用这种方法,那么有一个父Docker容器(用于更一般的系统级详细信息)和一个子容器(用于针对您的代码的设置)可能是有意义的。
评论
那为什么还要使用docker?
–lscoughlin
6月2日12:33
#6 楼
我认为更简单的解决方法是更改“上下文”本身。因此,例如,与其给出:
docker build -t hello-demo-app .
,它将当前目录设置为上下文,假设您想要父目录作为上下文,只需使用:
docker build -t hello-demo-app ..
评论
我认为这打破了.dockerignore:-\
– NullVoxPopuli
18 Mar 9 '18 at 23:25
我放弃了.dockerignore,而是制作了Makefile管理的docker文件夹,该文件夹仅包含构建上下文所需的文件...我只需要调用make build,它会提取所有需要更新的文件,然后调用适当的docker build。 ..我需要做一些额外的工作,但是由于我完全可以控制,它可以完美地工作。
– ah哈哈
19-11-26在9:33
#7 楼
您还可以创建首先需要图像的tarball并将其用作上下文。https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
评论
大提示!我发现您甚至可以将docker build tarball作为上下文输入到stdin:tar zc / dir1 / dir2 | docker build-。这对我来说非常有帮助。
–托尔·奥尔森(Tore Olsen)
5月9日10:54
#8 楼
如此GitHub问题所述,构建实际上发生在/tmp/docker-12345
中,因此类似../relative-add/some-file
的相对路径是相对于/tmp/docker-12345
的。因此,它将搜索/tmp/relative-add/some-file
,该错误消息中也显示了该错误。* 不允许包含来自构建目录外部的文件,因此将导致出现“禁止的路径”消息。
#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
#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/
评论
请注意,这仅在卷是运行时依赖项时才有效。对于构建时间依赖性,docker run为时已晚。
–user3735633
2月17日23:39
#11 楼
由于HIPAA的原因,我在项目和某些数据文件中遇到了相同的问题,因此无法在回购环境中移动。我最终使用了2个Dockerfile。其中一个构建了主应用程序,而没有我在容器外部需要的东西,并将其发布到内部仓库中。然后,第二个dockerfile提取该映像并添加数据,并创建一个新映像,然后将其部署且从未存储在任何地方。这并不理想,但出于我的目的,将敏感信息排除在存储库之外。#12 楼
链接的解决方法:ln path/to/file/outside/context/file_to_copy ./file_to_copy
在Dockerfile上,只需:
COPY file_to_copy /path/to/file
#13 楼
一种快速而肮脏的方法是根据需要将构建上下文设置为多个级别,但这会产生后果。如果您正在使用如下所示的微服务体系结构:
./Code/Repo1
./Code/Repo2
...
您可以将构建上下文设置到父
Code
目录,然后访问所有内容,但事实证明,使用大量存储库,这可能导致构建花费很长时间。示例情况可能是另一个团队在
Repo1
中维护数据库模式,而您的团队在Repo2
中的代码取决于此。您想用自己的一些种子数据来实现这种依赖性,而不必担心架构更改或污染其他团队的存储库(当然,根据更改的内容,您可能仍然不得不更改种子数据脚本)这种方法很笨拙,但却解决了构建时间过长的问题:
在
./Code/Repo2
中创建sh(或ps1)脚本来复制所需的文件并调用所需的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
目录的内容,而无需担心路径。 请记住,您将冒着将这个目录意外提交到源代码管理的风险,但是脚本清理操作应该足够容易。
#14 楼
就我而言,我的Dockerfile就像一个包含占位符的模板编写,我将使用我的配置文件将其替换为实际值。因此,我无法直接指定此文件,而是将其通过管道输送到Docker构建中,如下所示:
sed "s/%email_address%/$EMAIL_ADDRESS/;" ./Dockerfile | docker build -t katzda/bookings:latest . -f -;
但是由于管道的原因,
COPY
命令不起作用。但是上述方法可以通过-f -
(明确地说没有提供文件)来解决。仅执行不带-
标志的-f
,未提供上下文和Dockerfile,这是一个警告。
评论
这一定是Docker最糟糕的事情。从我的角度来看,没有“ Docker项目”之类的东西。 Docker用于运送项目。它只是一个工具。我不想重建整个项目来容纳docker,添加.dockerignore等。最终,谁知道Docker会持续多久?最好在代码之间(例如,角度项目)与部署它的任何方式(例如,docker)之间进行分隔。毕竟,在所有其他文件旁边放置一个docker文件确实没有任何好处。它只是为了创建图像而将其连接起来:(是的,这真是令人沮丧。我面临着同样的问题,我有一个较大的二进制文件(已压缩),不想复制到每个Docker构建上下文中。我宁愿从其当前位置(在Docker构建上下文之外)获取它。而且我不想在运行时映射卷,因为我试图在构建时复制/添加文件并解压缩并执行所需的操作,以便将某些二进制文件烘焙到映像中。这样可以快速旋转容器。
我找到了一个很好的结构,并在stackoverflow.com/a/53298446/433814
上进行了详细解释。
docker构建的问题是“上下文”的虚构概念。 Dockerfile不足以定义构建,除非将它们放置在战略目录(即上下文)下,即极端的“ /”下,因此您可以访问任何路径(请注意,在合理的项目中这样做不正确要么...,再加上它使docker的构建速度非常慢,因为docker在启动时会扫描整个上下文。您可以考虑使用所有必需的文件构建docker映像,并使用FROM从那里继续。我不会更改项目结构以适应Docker(或任何构建工具)。