Moby: 如何通过 Dockerfile 将多个图像合并为一个

创建于 2013-12-29  ·  97评论  ·  资料来源: moby/moby

我有几个 Dockerfiles 来构建图像,例如设置一个 postgresql 客户端,设置一个通用的 python 应用程序环境

我想为我的 python webapp 制作一个 Dockerfile,它结合了这两个图像,然后运行更多的命令

如果我正确理解文档,如果我第二次使用FROM我开始创建新图像而不是添加到当前图像?

arebuilder kinfeature

最有用的评论

我可以看到如何做到这一点,即genericA --> specificA但有什么办法可以做到:

genericA --
            \
             ---> specificAB
            /
genericB --

?

所有97条评论

你链接他们:)

因此,例如,如果您有一个 Dockerfile 来设置您的通用 postgres 客户端和通用 python 应用程序环境,您可以标记该构建的结果(例如mygenericenv ),然后您后续的 Dockerfile 使用FROM mygenericenv .

例如

## Dockerfile.genericwebapp might have FROM ubuntu
cat Dockerfile.genericwebapp | docker build -t genericwebapp -
## Dockerfile.genericpython-web would have FROM genericwebapp
cat Dockerfile.genericpython-web | docker build -t genericpython-web -
## and then this specific app i'm testing might have a docker file that containers FROM genericpython-web
docker build -t thisapp .

我可以看到如何做到这一点,即genericA --> specificA但有什么办法可以做到:

genericA --
            \
             ---> specificAB
            /
genericB --

?

不是通过任何官方方式,但有些人已经幸运地手动修改了图像层次结构来实现这一点(但如果您这样做,您需要自担风险,并且您可以保留所有部分)。

这不会得到官方支持的原因是因为想象一下我想把“ubuntu”移植到“centos”之上。 会有很多非常有趣的冲突导致支持噩梦,所以如果你想做这样的事情,你就靠自己了。

好的,我明白为什么了。 我一直在寻找可组合的功能块,但也许这不是 Docker 用例......似乎我应该使用它来设置原始容器,然后在顶部运行诸如 ansible 或 saltstack 之类的东西来配置其中的软件。

容器背后的想法是,真正组成的最小单位是容器。 也就是说,容器是你可以提前生产的最小的东西,不知道它还会结合什么,并且对它的行为方式和与其他组件的交互方式有很强的保证。

因此,任何小于容器的单元——无论是 ruby​​ 或 shell 脚本、c++ 源代码树、自身的二进制文件、一组配置文件、系统包等——都不能安全地组合,因为它会运行非常不同,这取决于它的构建依赖项、运行时依赖项以及其他哪些组件是组合的一部分。

这种现实可能会被蛮力部分掩盖。 这种蛮力可以是实用的并且“足够好”(巨大的 Makefile 可以自动检测所有内容以构建更可移植的应用程序)或过于浮夸(“让我们提前对组件之间的每个依赖项和干扰的每个可能排列进行建模,并表达它们处于高级抽象!”)

当您依赖 Ansible、Chef 或任何其他配置管理来创建“可组合组件”时,您依赖的是一个有漏洞的抽象:这些组件实际上不是可组合的。 从一个系统到下一个系统,他们将生成以一百万种方式表现不同的构建。 所有额外的抽象最终都会给你带来很少的收益。

我的建议是关注两件事:1) 源代码,以及 2) 可运行的容器。 这是仅有的 2 个可靠的构图点。

在Sun,2013年12月29日在下午1点46,anentropic [email protected]
写道:

好的,我明白为什么了。 我一直在寻找可组合的功能块,但也许这不是 Docker 用例......似乎我应该使用它来设置原始容器,然后在顶部运行诸如 ansible 或 saltstack 之类的东西来配置其中的软件。

直接回复此邮件或在 GitHub 上查看:
https://github.com/dotcloud/docker/issues/3378#issuecomment -31326172

感谢您提供更多的视角。

所以你是说为了重用 Dockerfiles 的一部分,唯一可用的工具是复制和粘贴? 从更多的“开发”而不是“操作”的角度来看,感觉有点不对。

也许拥有图像的公共索引是一个错误,它使您似乎可以共享类似于 Chef 食谱的可重用构建块,但到目前为止我的经验是它没有用,因为:
a) 对于大多数图像,没有关于它做什么和里面有什么的信息
b) 文档鼓励将您的工作提交给索引(以便您以后可以提取它),即使您所做的可能对其他人没有用,我猜那里的大部分内容可能不值得分享

我觉得这些文档目前并没有真正指导您以明智的方式使用 Docker

@anentropic使用 Dockerfiles 执行此
这是一个示例:Dockerfile 1 在 Ubuntu 基础映像之上构建通用映像,Dockerfile 2 使用 Dockerfile 1 的生成映像为数据库服务器构建映像,Dockerfile 3 使用数据库服务器映像并将其配置为特殊角色.

docker build应该很容易运行,不应增加不必要的复杂性。

图像的公共索引非常有用。 Docker 镜像通常用于运行一个服务或一组不能在单独容器中运行的服务。 您通常可以轻松地拉取映像,运行它并启动和运行一些有用的软件。

明白了……所以在我上面用 ascii 艺术概述的场景中,Docker 的方式是:

  • 从用于独立镜像的 Dockerfiles GenericAGenericB
  • 要制作图像SpecificAB我会将GenericB Dockerfile 的内容复制并粘贴到以以下内容开头的新 Dockerfile 中: FROM GenericA

我看到的问题是,如果GenericB的“食谱”(借用厨师术语)非常复杂并且有很多步骤,我无法共享此信息,除非通过发布 Dockerfile _to Github_ 所以其他人可以_复制和粘贴_相关部分到他们自己的 Dockerfile 中。

您是否尝试过使用公共索引? 例如,我搜索了“postgres”……我如何判断(或以任何方式区分)图像的有用性,例如:

?

当确保我按照我想要的方式设置 Postgres 服务器的唯一方法时,这些提供什么价值,在特定的基础图像上,没有隐藏任何狡猾的东西,将是我自己从头开始创建它。

我可以在公共索引中看到一些“官方祝福”基础图像的价值。 我可以看到准备好从中提取我自己的自定义图像的私有索引的价值。

但似乎没有办法(除了复制和粘贴)将 Dockerfile 中的一系列命令作为配方共享……例如此处拒绝的“包含”命令的建议https://github .com/dotcloud/docker/pull/2108

@anentropic您可以使用受信任的镜像,也可以找到 postgres Dockerfile 来自己构建镜像。

当您自定义 Dockerfile 以确保它们满足您的确切需求时,图像通常更有用。 这就是您发现更多用户将同一软件的图像上传到注册表的原因。

现有的特定图像(如 postgres 图像)可能无法满足您的特定需求,但也有基础图像,这些图像可以立即用于构建对您有用的东西。

ubuntucentos和一些来自stackbrew/*基本图像是您可以用来构建所需内容的图像。

一个很好的即用型图像的例子是stackbrew/registry 。 一旦docker pull stackbrew/registrydocker run -p stackbrew/registry执行完毕,这个镜像就可以让你使用私有的 Docker 注册表。

Docker 的目标是帮助部署和准备软件运行的环境。 这意味着构建是线性的,并且仅在初始构建期间完成,但您每次都将运行完全相同的软件。

配置管理系统可能允许您做更多事情或使用其他一些技巧,但它们并不是“一成不变的”,您最终可能会拥有两台主机,它们具有配置管理软件无法识别的细微差异。

讨厌死掉一个旧线程,但想提供一些恕我直言有助于解决原始海报问题的东西,并且可能会帮助其他人在这里寻找类似的解决方案。

让我们为简单起见假设它们都使用相同的基本图像R 。 想象一下,我有服务A和服务B 。 我希望它们在单独的 Docker 映像中,并且都在同一个 Docker 映像中。

编写一个脚本来安装服务A并编写一个单独的脚本来安装服务B 。 然后有一个带有A脚本的 git 仓库和另一个脚本B的 git 仓库。 为将要构建的所有三个 Docker 映像创建 git repos。 每个都包含 git 子模块以及将要使用的安装脚本。 每个 Dockerfile 将简单地ADD一个安装脚本,然后RUN安装脚本,并为一个或两个脚本执行此操作。 如果您希望从图像中删除脚本,请在运行后添加该脚本。

这样,每个安装脚本和您想要使用它们的任何 docker 图像都有一个副本。 这避免了不必要的代码复制并使维护负担最小化。 唯一的重复工作是将子模块使用的提交向上移动,这比替代方法要好得多,并且可能可以自动化。

我想我误解了这是如何工作的,所以我正在回复以获得澄清。 我想将 Ubuntu 11 与官方 selenium docker 图像一起使用。 他们使用 Ubuntu 15。

https://github.com/SeleniumHQ/docker-selenium/blob/master/Base/Dockerfile

我这样做的正确方法是什么? 要克隆该存储库并编辑所有文件以说是 Ubuntu 11 而不是 15? 这不可能是对的,对吗? 这意味着每个对官方图像的任何方面有任何异议的人都不能在不复制它们的代码的情况下使用它们。 我想我错了,有人可以解释一下吗? 在 Ubuntu 11 中使用官方 selenium 映像的正确方法是什么?

@rjurney是的,这就是它的工作方式; 在你的例子中,整个 Dockerfile 是用ubuntu:15.04开发的; 这些软件包在ubuntu:11上可用

“交换”现有镜像的基础镜像也行不通,因为 Docker 只存储基础镜像和镜像之间的 _differences_。 因此,使用不同的基本映像会导致不可预测的结果(例如,“删除文件 X”,其中“文件 X”存在于原始基本映像中,但不存在于您选择的基本映像中)。 此外,在基本映像“之上”构建的映像中的包/二进制文件是为 _that_ 版本构建的包,这些二进制文件可能与不同的基本映像不兼容。

这意味着每个人对官方图像的任何方面有任何分歧都不能在不复制它们的代码的情况下使用它们

是的。 官方镜像由这些镜像的维护者(在这种情况下,是 Selenium 的维护者)提供支持。 如果您认为需要对这些图像进行更改,最好的方法是在其存储库中打开功能请求。 如果该功能请求不被接受,您可能应该构建自己的版本。

(另请注意,没有官方ubuntu:11图像)

在软件世界的其余部分,单继承不被视为
足以合理地表达所需的语义。 它导致很多代码
重复,这将被视为一个错误。 为什么这被视为
码头工人可以接受吗? 即使您一次构建一项服务,
需要在操作系统级别进行组合。 我不是要打败一个
死马,不过这个限制好像有点极端。 可能会更好
表示为最佳实践? 由于这种严格
决定,有人会构建一个工具来组合或多重
继承并通过单继承和复制来表达它们。
将其置于 docker 之外不会为 docker 社区服务。

2015 年 12 月 9 日,星期三,Sebastiaan van Stijn <
[email protected]> 写道:

@rjurney https://github.com/rjurney是的,这就是它的工作方式; 在
你的例子,整个 Dockerfile 是用ubuntu:15.04开发的;
这些软件包在ubuntu:11上可用
在他们? 可能需要在 Dockerfile 中进行修改
使其在另一个版本的 Ubuntu 上工作。

“交换”现有图像的基本图像也行不通,因为
Docker 只存储基础镜像和
图片。 因此,使用不同的基础图像会导致不可预测的
结果(例如,“删除文件 X”,其中“文件 X”存在于原始基
图像,但不在您选择的基本图像中)。 此外,包/二进制文件
在基本图像的“顶部”构建的图像中,是构建的包
对于 _that_ 版本,这些二进制文件可能与不同的版本不兼容
基础图像。

这意味着每个人对任何方面有任何分歧
官方图片不能在不复制代码的情况下使用它们

是的。 官方镜像由这些镜像的维护者支持
(在这种情况下,是 Selenium 的维护者)。 如果你认为改变
需要这些图像,最好的方法是在
他们的存储库。 如果该功能请求不被接受,您应该
可能会构建您自己的版本。

(另请注意,没有官方的 ubuntu:11 图像)


直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -163188299。

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

@rjurney多重继承也极其复杂,而不仅仅是您在不考虑后果、极端情况和不兼容性的情况下添加的东西。

12749 是添加此类功能的最新尝试——最终被拒绝,因为还有其他工作要先完成。

构建器上有很多工作要做,包括启用客户端驱动的构建,这可以打开很多。

单继承 Dockerfiles 适用于(绝大多数)用例,因此不急于增强它。 它需要正确和慎重地完成。
根据您上面的评论,我会说您实际上并不需要多重继承,只是一种指定运行 Dockerfile 的基本映像而不复制现有代码的方法。

那将满足我的需求,是的。 能够修改某些属性
dockerfiles 链。

好的,很高兴听到你在这上面。 谢谢你的耐心 :)

在周三,2015年12月9日在上午9时59分,布莱恩·高夫[email protected]写道:

@rjurney https://github.com/rjurney多重继承也是
极其复杂,而不仅仅是你不加思索地添加的东西
对于后果、极端情况和不兼容性。

12749 https://github.com/docker/docker/pull/12749是最新的

尝试添加此类功能 - 最终被拒绝,因为有
首先要做的其他工作。
构建器上有很多工作要做,包括启用
客户端驱动的构建可以打开很多东西。

单继承 Dockerfiles 适用于(绝大多数)用例,
因此,不急于加强这一点。 它需要正确地完成并且
故意地。
根据您上面的评论,我会说您实际上并不需要多个
继承,只是一种指定运行 Dockerfile 的基础镜像的方法
反对而不复制现有代码。


直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -163340165。

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

@rjurney你从哪里得到你的信息。 据我所知,Java 从来没有多重继承,也永远不会。 我相信许多语言也是如此。 许多人认为多重继承极其有害,因为它会导致几乎无法预测的代码。 对于 docker 容器也是如此。

在我看来,我们需要 docker 的不是多重继承的概念,而是包含或外部依赖的概念。 例如,您可以在运行时挂载容器。 真正需要的是一种与图像等效的方法。 因此,例如,您可以拥有一个定义为基于 Fedora 22 的镜像,并挂载一个 oracle 镜像以添加数据库功能。

这在运行容器时可以非常成功地完成,但是没有使用图像指定它的语法。 因此,在运行时之前,docker 无法了解这些依赖项,也无法以任何方式为您管理它们。

请注意,我提到了多重继承和组合。
组合是做到这一点的首选方式,当然。

我同意你说的所有其他内容,所以 +1。

2015 年 12 月 9 日,星期三,Bill C Riemers通知@github.com
写道:

@rjurney https://github.com/rjurney你从哪里得到你的信息。
据我所知,Java 从来没有多重继承,也永远不会。
我相信许多语言也是如此。 许多人认为多
继承极其有害,因为它几乎不可能导致
可预测的代码。 对于 docker 容器也是如此。

在我看来,我们需要 docker 的不是多重的概念
继承,但包含或外部依赖项的概念。 例如
您可以在运行时挂载容器。 真正需要的是一种方法
相当于图像。 所以你可以例如有一个图像
被定义为基于Fedora 22,并挂载oracle镜像添加
数据库功能。

这在运行容器时可以非常成功地完成,但是有
只是没有用图像指定它的语法。 所以直到运行时没有
docker 可以了解这些依赖项或以任何方式管理它们的方式
你。


直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -163351035。

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

在这之后我要闭嘴了,但我错误地把这个咆哮放在了前面提到的拉取请求而不是这张票中。 所以我把它放在这里。

有人要建造这个。 不接受添加 INCLUDE 的 pull 将延迟和外部化此功能。 这应该是这里决定的基础:应该在 docker 内部还是外部 docker?

我想到了一个例子。 在 Apache Pig 中,尽管有很多要求,但团队还是决定不包含循环,因为他们认为 Pig 应该非常适合 DAG 数据流,仅此而已。 相反,创建了一个集成来编写 Pig 脚本,因此您可以循环使用任何 JVM 语言的脚本。 请注意,这是一个有意识的决定,并寻求替代方案。 这就是我认为的模型过程。

另一个 Pig 示例浮现在脑海中…… Pig 宏。 他们不存在并且是“非猪”,直到有人(好吧,我)开始讨论他们的大型猪项目有多么丑陋,并且如果不从外部工具生成 Pig 就无法解决这个问题,这是不受欢迎的。 许多人附和,Pig 团队添加了宏。 宏使清洁猪成为可能,社区受益。

我建议你直接解决这个决定并围绕它进行讨论,这在这里还没有发生,为了可查找性可能属于这里。 这将存在。 用领域特定语言复制脚本是很糟糕的。 人民会要求的。 这个特性是在 Docker 内部还是在 Docker 外部? 您将如何在 docker 之外促进这种行为?

抱歉,我可能在邮件列表中遗漏了很多上下文,但作为一个新的 Docker 用户......如果无法从现有配方中组合 dockerfiles,我对使用 Docker 做很多事情感到非常犹豫。 我和小猪一起走在这条路上,它差点害死我。 我想很多人都会有这种感觉。

万一有人关心...

关于 Pig 中循环和宏的半采用演示: http :
猪宏 JIRA: https :
Pig JIRA 的 API 接口: https :
一个被彻底拒绝尊重 Apache Hive 的人......向 Pig 添加 SQL: https :

最后,我有一个想法可以让这个改变变得容易……如果 INCLUDE 的文件不能继承怎么办? 也就是说,您可以通过让事情保持超级简单来避免反对。 随着了解的更多,稍后再处理其余的。 例如,可能有一个简单的 Dockerfile 来安装 pre-req 和二进制文件,并在 Ubuntu 上为 MySQL 设置守护进程。 如果需要,这可以通过 Ubuntu 和 MySQL 的版本进行版本控制。 就个人而言,我将编写一个实用程序来执行这些简单的 INCLUDE,并使用它以这种方式组织我的 dockerfile。 我迫不及待地订购并重新使用我的代码。

+1 为 INCLUDE 想法。 虽然我相信禁止继承只会改变问题,因为现在您可以修改您继承的主流图像,但不能修改您包含的其他图像。 基本上,如果您可以将映像指定为“可包含的”,因为它不提供任何可能破坏现有基本映像内容的操作系统内容,那么什么才是有意义的。 此标志必须由 docker 构建过程设置,并防止包含未充分标记的图像。 我的意思是让我们面对现实。 如果你在玩 Dockerfiles,你可能不是第一天看到他的机器的人,所以我相信虽然阻止 docker 的最终用户做愚蠢的事情是有道理的,但应该多一点真正创造这些图像的人的自由。 我的意思是说真的,能够选择一个基本图像并将我想要的所有内容包含在其中以配置我的应用程序将非常棒。

+1 表示包含。 我只需要将 nginx 和 ssh 图像合二为一。 为什么要这么难?

坦率地说,这种不需要的想法令人困惑到存在的地步
不诚实的。 如果创建,大多数用户将使用它。 "将 ssh 添加到
ubuntu”和“将 nginx 添加到 ubuntu”是每个人都很常见的任务
不必重复。 docker HQ 似乎真正在说的是,
“显然需要,但我们认为它会变得太难看。所以我们假装。” 它
如果你真的能坦诚相见,那就更好了。
对不起,如果我脾气暴躁。

2016 年 1 月 23 日星期六下午 6:22,Vazy [email protected]写道:

+1 表示包含。 我只需要将 nginx 和 ssh 图像合二为一。 为什么
这有必要这么难吗?


直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -174243875。

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

@rjurney让我们等待构建分拆; 因为这样,将有不止一种方法来构建图像(因此可能会出现一个自定义构建器来做到这一点)。 Docker 维护者(为 Docker 工作或不为 Docker 工作)对此感到兴奋的原因之一是,它会增加我们想要增加灵活性和简单性的复杂性。 通过提取构建器,我们将有更好的关注点分离(构建图像和运行它们之间),并且许多用例将在自定义构建器中更自由地实现。

再说一次,您是否将其从项目中推出? 自定义声音...不是
默认的包含方式。 事实上,包含是一个简单的需求
大多数人都有。 重复自己是复杂的。 继承只是
复杂。 包括以最简单的方式满足每个人的需求
可能的。

2016 年 1 月 24 日,星期日,Vincent Demeester通知@github.com
写道:

@rjurney https://github.com/rjurney让我们等待构建分拆;
因为这样,将有不止一种方法来构建图像(因此
可能会出现一个自定义构建器来做到这一点)。 原因之一 docker
维护者(为 Docker 工作或不工作)对此很感兴趣,是
因为它会增加我们想要增加灵活性和的复杂性
简单。 通过提取构建器,我们将更好地分离
关注(在构建图像和运行它们之间)和大量用例
将在自定义构建器中更自由地实现。


直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -174423973。

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

+1,组合图像将非常有用。 想象一个(上帝保佑)C++ 用例。 我用 boost 构建了一个想象,另一个说 Qt,都使用相同的编译器,等等。现在说我想用 boost 和 Qt 构建一个应用程序,我只需要将两者结合起来,presto - 一个准备好的开发环境。 这将非常有用。

就个人而言,我觉得这是一个非常重要的问题,无法解决。 话虽如此,无论在何处实施,我们都需要很好地了解问题和范围是什么。

所以,我看到了合并带来的这些问题。

  1. 处理合并冲突。
  2. 解决不同的基础(Ubuntu 和 CentOS)。

对于第一个,我认为简单的答案是不要。 对我来说,这听起来很复杂,而且可能有问题,需要一套工具来解决,但仍然可能太神奇了。 所以,如果添加了这个,合并冲突应该会失败。 我想它可以在以后重新访问,但这似乎比它值得的麻烦更多。

至于第二种情况,您似乎可以添加一个约束,让它们共享一些基础层。 现在的问题变成了多少就足够了。 我认为开始时的正确答案是合并的两个图像必须具有相同的FROM图像。 这里可能需要更多的限制,但我不清楚这些情况是否属于问题 1,问题 1 已通过简单地禁止它来解决。

我在这里还缺少其他一些问题吗?

我认为不应该尝试合并......我看不到这种情况发生

更现实的方法可能是模板类型的解决方案,即允许INCLUDE一个 Dockerfile _fragment_(它没有FROM子句,只有一个命令列表)到一个真正的 Dockerfile 中......可以针对任何兼容的基础镜像 Dockerfile 共享、重用和包含片段

我对 Docker 完全陌生,并且虚心学习。 但我认为 Docker 的主要目的是构建非常小的 _reusable_ 应用程序,以便以后以任何方式将它们组合成伟大的大型最终应用程序,如在 Web 应用程序中。 如果是这样,恕我直言,像INCLUDE这样的声明是强制性的。

@jmcejuela在许多情况下,“重用”是创建专用于特定服务的图像,并组合这些图像/容器以形成您的应用程序。 应用程序的各个组件是可重用的(可能只是容器的配置不同),但是将它们组合在一起的方式构成了实际的应用程序。

@thaJeztah我明白了,谢谢。

但是让它像之前发布的人一样具体,假设我构建了一个运行 scala 应用程序的 Web 应用程序(图片A ),然后使用 nginx 制作 Web 服务器(图片B ),然后使用 ssh (图像C ),并且需要一个额外的 python 应用程序(图像D )。 假设我为每个创建了 4 个 Dockerfile。 我如何将它们与 Docker 结合起来创建我的最终 Web 应用程序(图片E ?)

我只需要一个简单的方法来做到这一点。 我不关心关于多重继承的哲学争论,包括与否,撰写与否,等等。虽然我当然不想像以前提出的那样复制和粘贴。

非常感谢您的参与。 我还在学习Docker。

@jmcejuela您不会组合 _images_,而是将它们作为单独的容器运行,并让它们合作形成应用程序。 您可以使用 Docker Compose 来实现,它允许您定义“堆栈”。 例如,请参阅https://github.com/docker/example-voting-app/blob/master/docker-compose.yml (以及自述文件;https://github.com/docker/example-voting-app/ blob/master/README.md)

对于“ssh”部分,这真的取决于你想用它做什么; 总体而言,容器被认为是“不可变的”,因此您不会通过 SSH 进入容器并对其进行修改,而是启动一个新容器来替换旧容器; 需要在容器生命周期后持续存在的数据然后存储在卷中,以便新容器可以使用这些文件。

@jmcejuela Docker builder 在 STDIN 上接受 Dockerfile 内容,所以可以“相对”轻松地生成一个? 如果必须传递上下文,则所有内容都应进行焦油处理并输入docker build 。 根据我的经验,这是获得构图的最简单的方法。

我正在开发(并使用)一种建立在上述概念之上的方法。 nodejs 应用程序在内存中准备 TAR 文件(带有Dockerfile和添加的文件)并将其转储到 STDOUT。 STDOUT 被传送到docker build 。 可组合部件作为 NPM 模块进行版本控制、测试和发布。 我举了一个很短的例子,它演示了crond的测试图像 - http://pastebin.com/UqJYvxUR

谢谢@thaJeztah最后,我只需要一个文件,我的合作开发人员可以运行该文件来拥有整个开发堆栈,然后也可以在需要时在 prod 上运行它。 我将更深入地研究 docker compose。

另外,很久以前就提出了INCLUDE (https://github.com/docker/docker/issues/735)。

@jmcejuela事实上,大多数

只有当你做错了, docker exec命令已经存在了很长一段时间,而且我从来不需要 ssh 自从......

@anentropic仅当您部署没有依赖项的简单服务时才成立。 如果您有任何服务的复杂依赖链,例如任何涉及机器学习的东西,您将复制代码来部署服务。 而且没有充分的理由你应该这样做。 仅仅因为 docker 是一种特定领域的语言,并不意味着关于编程语言的大量知识被抛在了外面,旧的课程也不适用。 理智仍然需要重要。 复制和粘贴食谱是疯狂的。

它也仅在您订阅“单一服务”世界观(并非所有 docker 用户)时才成立。

@anentropic根据 Docker路线图,通过docker exec运行容器可能(来)同样错误。

PS rkt引擎已经达到 v1.0。

@rjurney ,:100:

多重继承无论是被爱还是被恨都是一个复杂的特征,无疑会产生阻力。 Include 将 Dockerfiles 从构建配方转变为具有难以解决的路径问题的语言。

如果我们以不同的方式看待问题会怎样。 如果我们能够“ ADD / COPY ”从另一个docker镜像中选择文件到正在构建的镜像中会怎样。 通过这种方式,人们可以从重用功能中受益并避免代码重复。 由于我们没有在图像中多次使用FROM ,而只是以显式方式复制二进制文件,因此这应该以明确定义的方式运行,否则就是失败。 鉴于这适用于 docker 图像,并且它能够利用注册表作为解决方案而不是一些新的搜索路径,我希望这是一个合理的建议。 一个额外的好处是我们也不必多次重新运行相同的代码。 此外,希望可以避免对构建器的大规模更改。 想法?

也许这是在其他地方提出的,在这种情况下,链接会很好。

你好,
无论选择什么解决方案,从多个独立来源准备图像都是我非常惊讶的事情,这是不可能的。
我本来希望跳过图像准备,因为在运行时我们可以执行此过程,以便在运行时部署一组图像,无需在每次修改依赖项时重新制作图像。
我搜索了替代品,还没有找到任何有效的,这是一个主要的使用差距。
使用 ACI 看起来很容易执行。
谢谢!

:+1:很想解决这个问题,很高兴至少有人在谈论它。 即使它要求基本图像相同。

原来在别处建议从其他图像复制。 这是问题(https://github.com/docker/docker/issues/18596)。

谢谢@jakirkham ..

+1 用于 docker 多重继承功能

编辑:

另见: https :

我认为您遇到的问题是无法编写食谱是没有意义的。 Docker compose 非常适合在应用程序中使用多个容器。 Docker swarm 非常适合处理多个节点。 但在许多情况下,无法在源代码级别包含其他人的工作。 您必须继承一次或重新创建它,这是有限制的。

于星期五,2016年3月18日在上午09点01分,阿尔文Chevolleaux < [email protected]

写道:

@thaJeztah https://github.com/thaJeztah的回复非常
启发。 我是 Docker 的新手,不明白为什么你不能结合
多个 _images_ 在一起,但 Docker Compose 似乎是解决方案
将多个 _containers_ 组合成一个我正在寻找的应用程序
为了。

我认为我的问题是我一开始以为我了解 Docker
但现在我发现我没有。 我要回去做更多的事情
阅读!


你收到这个是因为你被提到了。
直接回复此邮件或在 GitHub 上查看
https://github.com/docker/docker/issues/3378#issuecomment -198426036

罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

@rjurney是的,在对 Docker Compose 进行了更多研究之后,您是对的,这正是我的困惑。 例如,有一个 PHP 图像和一个 Centos 图像,但不同图像之间没有继承,所以它有点全有或全无。 在官方 PHP 映像中,它使用debian:jessie但我希望我的设置基于 Centos,所以似乎如果我想使用特定的映像,我必须接受其余的设置或复制并粘贴源 Dockerfile并从头开始滚动我自己的图像,似乎没有中间地带可以混合和匹配图像。

编辑:
只是为了澄清我理解为什么你不能将基于 Ubuntu 和 Centos 的图像混合在一起,但我不明白为什么你不能有某种层次结构。 然后,您只需将更改从一个图像下载到另一个图像,而不是下载整个图像。

INCLUDE对我来说也非常有用。 没有它,我只能复制粘贴。

@RomanSavejev我不明白:

根据 Docker路线图,通过docker exec运行容器可能(来)同样错误。

它并不是说docker exec会被弃用。 docker exec一直是一个调试工具,Docker 容器中的 SSH 也应该如此。

我觉得参与这个很愚蠢,但到底是什么……我会再次建议:

为什么我们不简化问题并从实现 INCLUDE 开始,以便它不允许继承? 换句话说,您只能包含没有 FROM 的文件。

这将处理许多用例,推动人们在任何合理的操作系统上工作的文件。 uname 的存在是有原因的。 这将是第一步,对此实施的反馈将有助于进一步定义任何内容。

这似乎是一个容易做出的决定。 这不会是大量的工作。 它不会很复杂。 对?

@rjurney这基本上就是https://github.com/docker/docker/pull/12749所做的

@rjurney :不要觉得自己很愚蠢。 虽然 INCLUDE 并没有真正完全涵盖最初的询问,但它是朝着正确方向迈出的一步。 封装了几个问题。

  1. 如何将几件独立的作品结合起来?
  2. 如何有效地存储这样的汇编?
  3. 如何在二进制级别而不是构建级别组合几件工作?

可能还有更多项目可以添加到此列表中。 INCLUDE 解决方案处理第一个要点。 一旦到位,这就奠定了一个标准框架,其中二进制存储效率可以对最终用户透明地提高。 一旦到位,就可以讨论直接对图像文件进行相同操作的工具。 然而,这最后一步当然是非常值得怀疑的。 一旦您直接在图像文件上执行此操作,就有可能最终得到损坏的图像。 但是,如果假设只有高级用户(那些确切知道自己在做什么的人)会执行第三个选项,那么在我看来,这似乎不是一个不合理的补充……最终。

对于那些想要以这种方式真正可组合的东西,您可以查看 Nix(NixOS,一个 Linux 发行版和包管理系统)。 它只需要您重新打包所有软件,通常是从源代码构建,并放弃您认为对 Linux 了解的一切;)。 这是一个不错的系统,但由于使用它的人并不多,因此需要做很多工作,但我真诚地希望它能流行起来。

正如其他人所说,Docker 可组合性更多地是在服务级别进行组合。

:+1: defo 值得考虑一个可组合的模型——如果你能将行为导入到 dockerfile 中,那就太棒了。 例如,我现在有一个用例,我想在许多基于 Alpine linux 的非常不同的构建容器中包含 apache thrift - 有些将构建 Java 服务,其他 PHP 和其他 Node.js 服务。

能够包含 thrift 安装而不是复制和粘贴会很好 - 我想我可以很容易地提取到 shell 脚本,然后添加和运行它。

那么如何同时使用 ruby​​-2.3 和 java-8 图像呢? 他们使用相同的 debian jessie 图像作为基础(我阅读了 dockerfiles)。 我只想执行它们中存在的命令。 就目前而言,我必须将 Java Dockerfile 复制/粘贴到 Ruby Dockerfile 中。 该应用程序需要两者,我绝对无法解决这个问题。

我在粘贴时确实借此机会删除了一些 Dockerfile 命令 - 它们没有害处,但只是多余的,因为“基本”Dockerfile(我将命令粘贴到其中)已经执行了这些步骤。 因此,我可以看出我并不真正想要“ruby”和“java”图像的论点,我实际上是在构建第三个“ruby+java 多合一”图像。

但是,在这种特殊情况下,这两个图像中的命令似乎完全兼容 - 如果我只是将它们连接起来,它们应该可以工作。 能够具体说明这种情况会很有用。 我不是复制/粘贴方法的忠实拥护者 - 在我的例子中,Java 和 Ruby Dockerfiles 足够简单,但有些 Dockerfiles 复杂得多。

但是,对于像我这样想要此功能的其他所有人 - 我可以看到很多情况会出现问题。 因此,这不仅仅是提供在同一个 docker 映像上运行“nginx”然后“ssh”的能力的问题——同样的功能还可以让你运行“debian”和“centos”,这绝对不会产生可行的形象。 如果它被引入,它似乎必须是一个实验性选项,默认情况下关闭,其中附加了大量警告。

因此,无论此功能的接口是什么,都必须非常清楚地表明,获得可重用行为(命令集)的责任在于 Dockerfile 开发人员。

编辑:啊,我错过了包括讨论。

为什么我们不简化问题并从实现 INCLUDE 开始,以便它不允许继承? 换句话说,您只能包含没有 FROM 的文件。

这将处理许多用例,推动人们在任何合理的操作系统上工作的文件。 uname 的存在是有原因的。 这将是第一步,对此实施的反馈将有助于进一步定义任何内容。

这似乎是一个容易做出的决定。 这不会是大量的工作。 它不会很复杂。 对?

:+1:

@rjurney这基本上就是 #12749 所做的

:+1: 完美,期待看到它的最终形式能够做什么。

对这个概念也很感兴趣。 “INCLUDE”机制是一个非常粗糙的解决方案,但老实说,这代表了一组 docker 文件的可维护性向前迈出了一大步。

就我个人而言,当它遇到FROM ,我不希望它_fail_,我希望它_ignore_ FROM并按顺序应用其余的命令。

如果没有 FROM 支持,这还没有发生是一个开源
讽刺。

2017 年 1 月 19 日星期四上午 10:19,Ken Williams通知@github.com
写道:

对这个概念也很感兴趣。 “INCLUDE”机制是一个非常
粗略的解决方案,但老实说,这代表了向前迈出的相当大的一步
一组 docker 文件的可维护性。

我个人不希望它在遇到 FROM 时失败,我会
希望它忽略FROM 并只应用其余的命令
顺序。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/docker/docker/issues/3378#issuecomment-273854850或静音
线程
https://github.com/notifications/unsubscribe-auth/AACkpS8-EQ7r0BHid75rxeBDhOUDFRXlks5rT6kXgaJpZM4BWkJ9
.

——
罗素·朱尼 twitter.com/rjurney russell。 [email protected] relato.io

事情就是这样,我不一定需要合并。 我认为很多问题都可以通过 rebase 解决。 我的正常用例是

A (ubuntu) -> B (例如 nginx)
A (ubuntu) -> C (例如节点)

我想要一个组合的 B & C 图像。 通常它们彼此没有任何关系,因此只需将 A 和 C 之间的所有差异都重新设置为 B 就足够了。即

A -> B -> C'

这似乎是一个更容易解决的问题。

@cloutiertyler通常,Node.js 应用程序不需要此功能即可与 Nginx 一起使用(在我看来)。 Docker 的方式是两个容器,一个用于 Nginx,另一个用于 Node。 我们将 Node 容器配置为仅将其端口暴露给 Nginx 容器,并让 Nginx 容器侦听公共端口(如 80)。 为什么 Nginx 需要与 Node 在同一个容器中?

一个示例 Docker Compose 文件可能是

version: "2.1"

services:
  app: # Node.js application image
    build: .
  nginx: # Nginx container who can make request to app container
    image: nginx:1.10-alpine
    depends_on:
      - app
    ports:
      - "${PORT:-8080}:80" # public port, you may want PORT=80

@franklinyu我感谢回复。 我实际上只是以两个随机服务为例。 我通常的用例是从通用服务(例如基于 ubuntu 的节点)和我自己的自定义图像(也基于 ubuntu)开始,并希望将它们组合起来。

顺便说一句,它并不是完全重新定位,而是为 Dockerfiles 开辟了许多用例。
Dockerfile 现在支持多阶段构建。 例子:

FROM golang AS myapp
COPY . /myapp
RUN cd /myapp && go build

FROM scratch
COPY --from=myapp /myapp /usr/bin/myapp

您可以根据需要设置多个阶段。
--from参数基本上将上下文切换到指定的构建目标名称。
当您docker build -t myapp . ,名为myapp:latest的结果图像将来自最后一个阶段。
例如,您还可以使用docker build --target=myapp构建特定阶段。

17.05 中还有一些其他非常好的 Dockerfile 增强功能(目前作为 RC1 可用),试试看!

现在这很有趣! 我不知道你能做到这一点。 我将不得不尝试一下,看看它是否能解决我的常见用例。

虽然这是一个很棒的功能,但尝试过它并不能真正解决我最常见的问题。 我今天又碰到了。

我想要一个安装了 Docker 的 Jenkins 映像,以便我可以在容器内进行构建。 事实是,如果不在我的 Dockerfile 中复制一个或另一个的安装过程,就无法做到这一点。

在这种情况下,由于每个容器应该只是一个服务,因此不需要关于此的模糊争论显然不适用。 我的“一个服务”结合了 Docker 和 Jenkins 的功能。

事实是,如果不在我的 Dockerfile 中复制一个或另一个的安装过程,就无法做到这一点。

所以你想将两个 dockerfile 粉碎成一个,这样你就不必复制/粘贴东西了吗?

在这种情况下,复制/粘贴相当于分叉。 我想要做的是避免分叉 Dockerfile,这样我就不会错过错误/安全改进或其他更改,因为它以后总是会发生变化。

不能只是路过。 寻找一种在长链图像继承(比 2 更深)上分配更改的方法。 多阶段似乎不是澄清问题的东西。 拥有一个可以只包含指令块的实体,允许我将它包含到我所有的继承者图像中,与基本图像功能一起看起来像是理性进化。

对于那些想知道正确方法的人,从 Docker 的角度来看,花几分钟时间回顾一下:
https://github.com/floydhub/dockerfiles

在这里,他创建了一个完整的 Dockerfile 树。 当您沿着树向下走时,您会发现依赖项的不同组合,每个组合都来自树中的上一层。 所以如果你跟着树从
-ubuntu->common-deps->python3->deepLearningBase->pyTorch
你真的想要

-ubuntu->common-deps->python3->deepLearningBase->pyTorch 
+
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow 

您要做的就是在 deepLearningBase 下为两者添加一个节点(文件夹),例如
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow-pyTorch

现在,您仍然需要制作一个结合 pyTorch 和 TensorFlow dockerfiles 的 dockerfile,但是
他们的关键是这些文件将非常简单,只需在 deepLearningBase 上安装几行即可。

所以真正需要的是像这样的几个更大规模的 github 存储库,用于不同的“世界”,例如 Web 开发、深度学习、嵌入式软件等。

然后,您只需按照树进行所需的构建,如果还没有其他人完成,只需添加一个节点并组合 2 或 3 条 apt-get 行并创建新环境。

这看起来像是“选择你自己的冒险”风格的构图。 INCLUDE 会简单得多。 见鬼,我只想用nano组合一个指定的gcc图像,这样我就不必每次都从 apt-get 安装 nano!

我同意@chambm在他的上述评论中的看法。 在大多数情况下,这没有理由不可行(冲突应该相当罕见,因为它们在手动管理的操作系统上)。

这是一个与@cloutiertyler评论的用例非常相似的用例,其中@franklinyu解决方案@cpuguy83评论的多阶段构建都不适用:

在哪里:

  • 从 A 到 C 的步骤与从 B 到 D 的步骤完全相同(dockerfileAC)。
  • B 的开发团队对 C、D 或 E 一无所知。
  • C 的开发团队对 B、D 或 E 一无所知。

愿意构建 D(和/或 E)的用户必须有权访问 dockerfileAC,但不需要了解 dockerfileAB。 因此,用户必须对一个依赖项 (C) 比另一个 (B) 有更好的理解。 理想情况下,应该可以依靠团队 A 和 B,并将 D 构建为A + (diff(B,A) + diff(C,A)) (合并)或A + diff(B,A) + diff(C,A) (rebase)。

因为 GHDL 不是 Web 服务并且 VUnit 不是 Web 客户端,所以这两个工具都需要安装在同一个图像/容器 (E) 中。 多阶段构建没有用,因为我们需要构建一个(可能未知的)带有两个FROM标签的 dockerfile,它不是单个前向链。

如果发现这个用例类似于两个git分支的merge/rebase:有时没有冲突,有时冲突很容易解决,有时根本无法合并,因为没有共同的历史......有没有什么工具,官方或外部,提供此功能? 请注意,如果该工具只是将两个图像导出到 git 分支并实际使用 git 进行合并,则可以。

令人惊讶的是,这仍然是一个问题和话题。 “包含一些图像”有多难,然后在解析它时,检查基础是否兼容(在 FROM 链中),如果是,则在那时执行该文件的其余部分(就像我从项目中复制了 Dockerfile 一样并将其粘贴到我的中)?

在这种情况下,整个“人们会做他们没有意识到的坏事”的借口是荒谬的。 这已经非常复杂了,这就是为什么我们需要它来帮助简化它。

@rainabba这是一个完全没有帮助的评论。
基本上有两个原因导致它没有完成,要么:

  1. 没那么容易
  2. 没有人花时间做这项工作。

实际上,通常两者兼而有之。

  1. 这是一个解析和字符串替换问题,任何新编码人员如果知道代码中的位置,都可以在 10 分钟内完成。 我并不是说它在所有情况下都可以使用,但是对于我在这里一遍又一遍地建议的有限情况(其中基础实际上很常见),这是一个死局。

  2. 当然不是,这个线程提供了大约 102 个不能或不应该做的理由,那么为什么有人会想这样做呢?

另一方面,我的评论(就像这里的许多其他评论一样)表明有必要并希望影响阻碍态度或至少起到提醒作用。 如果这“完全没有帮助”,那么您刚刚解释了为什么这个问题(被忽略的功能请求)仍然存在并且很活跃,而且它不是技术问题。

它的方式比解析字符串更多。
Docker 和 Dockerfile 被数百万人使用。 添加 API 是一件很重要的事情……即使在此之外,底层实现也不是“解析字符串”。

无论如何,有许多解决问题的建议,这是一个非常古老且封闭的问题。

我确实认为,如果 Docker 没有为这种情况找到一个干净的解决方案,它可能会被任何能够解决问题的工具所取代。

我注意到我的一位同事使用以下模式,这可能是一个不错的解决方法:

ARG from
FROM $from
... rest of dockerfile

不过我自己还没有尝试过,所以我不确定它在实践中会如何工作,例如它在缓存中的表现等等。

的确,这是一个非常重要的问题,并没有得到妥善解决。 我很惊讶像 Docker 这样大的公司还没有解决这个问题。

只是我的两分钱......我现在只是在学习更多关于 Docker 的知识,我觉得像 INCLUDE 这样的东西会非常有用。 我喜欢上面的多重继承示例,并希望解决有关可能存在的问题和与之冲突的评论。

多重继承在任何支持它的语言中都很困难,但是当发生冲突时,Docker 文件创建者有责任重新思考他们在做什么并重新开始。 Docker 应该只构建镜像,而不是试图证明构建没有问题。

@cosminonea

我觉得像 INCLUDE 这样的东西会非常有用

我支持https://github.com/larytet/dockerfile-generator/中的宏,我也可以支持“包含”。

那将错过重点。 目标不是包含 Dockerfile
定义。 目标是包含 docker 镜像。 这将
看起来很荒谬,因为它不在我的脑海中:

来自软呢帽
包括 ubuntu /ubuntu
包括 debian /debian

合理地,我希望这从 Fedora 的形象开始。
然后在文件夹/ubuntu下添加ubuntu的图像。 然后添加了
/debian 下的 debian 图像。

这当然是荒谬的,那我为什么要混合一堆操作
系统成一个形象? 但更有用的例子可能是:

来自软呢帽
包括丛/丛
包括 commericalremover /plex/add-on/commericalremover

现在在这种情况下它更有意义。 如果这些是其他图像
没有操作特定的组件 我有一个简单的方法来制作东西
模块化的。

2018 年 8 月 8 日星期三 15:48,Arkady Miasnikov通知@github.com
写道:

我觉得有点像 INCLUDE
我支持宏
https://github.com/larytet/dockerfile-generator/我可以添加“包含”
也支持。


您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/3378#issuecomment-411529506或静音
线程
https://github.com/notifications/unsubscribe-auth/ADBcWAtBDEp_LXpW3HUkHd3Pw5IVAXvqks5uO0ChgaJpZM4BWkJ9
.

最后一个已经是可能的了; COPY --from接受构建阶段或图像,例如;

FROM busybox

COPY --from=alpine:latest / /
COPY --from=docker:latest /usr/local/bin/docker /usr/local/bin/

编辑; 或以实际例子为例;

FROM fedora

COPY --from=ubuntu:latest / /ubuntu/
COPY --from=debian:latest / /debian/

确切地。 这就是为什么我会考虑添加“COPY”的 2017 年更新
--from”作为完成了原始请求。绝对有
我没有从这张票中寻找更多。

后来提出的想法,如自动重新调整包含的基础,将是
不错的功能。 但他们确实超出了最初的要求。

问候,

账单

2018 年 8 月 9 日星期四 12:55,Sebastiaan van Stijn通知@ github.com
写道:

最后一个已经是可能的了; COPY --from 接受
构建阶段或图像,例如;

从繁忙的盒子

复制 --from=高山:最新//
复制 --from= docker:latest /usr/local/bin/docker /usr/local/bin/


您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/3378#issuecomment-411824851或静音
线程
https://github.com/notifications/unsubscribe-auth/ADBcWPE738cs9xf3ZHSOaUd1foI1XVIQks5uPGmYgaJpZM4BWkJ9
.

@thaJeztah 为此使用多阶段构建仍然需要您知道要从每个图像 _exactly_ 复制哪些文件; 这比从另一个图像复制粘贴设置代码更难维护。

当然,合并 Docker 镜像并非易事。 由于可以在构建期间运行任意脚本,因此构建过程抵制任何自动冲突检测的一般尝试; 停机问题说嗨! 你能做的最好的事情(没有显着限制构建可以做什么)是定义精确的语义:说最后一个FROM / INCLUDE获胜(例如,如果他们“写”同一个文件)或在文件系统级冲突或....

有时会提到不同“基本”图像的问题(stretch vs ubuntu vs alpine vs ...),但是,_is_ 很简单:要求图像依赖项的 DAG 不仅具有单个源(当前图像)而且还有单个接收器(“层次结构”中所有图像的共享“祖先”)。

最终,当然,你会得到垃圾中的垃圾——真的有什么不同吗?

FWIW,我的用例是:

  1. 使用 PostgreSQL 数据库和 S3 对象存储运行 Tomcat Web 应用程序。
    虽然这可以通过使用 Docker Compose 来解决,但单个容器可能更好。
  2. 多语言构建在 Docker 容器中运行(例如在 Jenkins、Circle CI 上,...)。
    大多数流行的工具链都有官方映像,但是在此处讨论的问题中,要配备一个容器来处理多个运行。

@reitzig这不是唯一的选择。 正确的选择是限制 INCLUDE 以避免出现大问题。 INCLUDE 不能继承。 就是这样。 简单的。 仍然非常有用。

此功能请求很受欢迎,但 Docker 与 Beer 一样免费,但绝不像 Freedom 中那样免费。

@rjurney自 18.06 起包含 buildkit 支持,用户可以为构建器提供自己的前端解析器。 已经有一个官方(来自 Docker Inc)实验性 Dockerfile 解析器,其中包括许多新功能(支持初学者的秘密)。

您当然也可以在自定义 Dockerfile 前端中添加您自己的“包含”行为,或者您可以做一些完全不同的事情,根本不是 Dockerfile(有一个 buidpacks 的示例)。

要使用自定义前端,只需将 Docker 指向可以处理它的图像。 将此作为对 Dockerfile 第一行的注释(或其他任何内容) syntax = myCustomFrontendImage

更多细节在这里:
https://docs.docker.com/develop/develop-images/build_enhancements/#overriding -default-frontends

启用 buildkit 后,Docker 可以使用您需要的任何功能构建您想要的任何内容(甚至不必是 Dockerfile 格式)。

此功能请求很受欢迎,但 Docker 与 Beer 一样免费,但绝不像 Freedom 中那样免费。

尽管该说明是离题的,但我认为应该指出您错了。 多亏了 Docker 的 Apache 许可,每个人都可以自由地为 Dockerfiles 分叉和开发自己的解释器,提供这里开发的功能。 如果他们小心,生成的图像将与现有的 Docker 运行时/工具兼容。
当然,Docker 项目的维护者同样可以自由地不将这样的功能合并到他们的 fork(原版?)中。

@reitzig这显然只是毫无意义的咆哮,而没有真正提到什么是自由软件。 Moby 当然是免费软件。

我不知道它现在是 Apache 许可的。 我为这句话道歉,并
觉得这很棒!

Russell Jurney @rjurney http://twitter.com/rjurney
罗素。 [email protected]http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

2019 年 1 月 16 日星期三凌晨 4:17,Raphael R. [email protected]写道:

此功能请求很受欢迎,但 Docker 与 Beer 一样是免费的,但不是
任何手段像在自由中一样自由。

尽管该注释是离题的,但我认为应该指出的是,您是
错误的。 多亏了 Docker 的 Apache 许可,每个人都可以自由地
fork 并为 Dockerfiles 开发自己的解释器,提供
这里开发的功能。 如果他们小心,生成的图像将是
与现有的 Docker 运行时/工具兼容。
当然,Docker 项目的维护者同样可以自由地不
将这样的功能合并到他们的分支中(原始的?)。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/3378#issuecomment-454758482或静音
线程
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

对不起,我没睡好,我弄错了。 我的意见成立。
免费,因为在啤酒中意味着 Apache。 在自由中自由意味着社区控制。
Apache 项目或其他某种形式的治理。

Russell Jurney @rjurney http://twitter.com/rjurney
罗素。 [email protected]http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

2019 年 1 月 16 日星期三下午 12:32 拉塞尔·朱[email protected]
写道:

我不知道它现在是 Apache 许可的。 我为这句话道歉,并
觉得这很棒!

Russell Jurney @rjurney http://twitter.com/rjurney
罗素。 [email protected]http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

2019 年 1 月 16 日,星期三,凌晨 4:17,Raphael R. [email protected]
写道:

此功能请求很受欢迎,但 Docker 与 Beer 一样是免费的,但不是
任何手段像在自由中一样自由。

尽管该注释是离题的,但我认为应该指出的是,您是
错误的。 多亏了 Docker 的 Apache 许可,每个人都可以自由地
fork 并为 Dockerfiles 开发自己的解释器,提供
这里开发的功能。 如果他们小心,生成的图像将是
与现有的 Docker 运行时/工具兼容。
当然,Docker 项目的维护者同样可以自由地
不要将这样的功能合并到他们的分支中(原始的?)。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/moby/moby/issues/3378#issuecomment-454758482或静音
线程
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

免费,因为在啤酒中意味着 Apache。

不同意。 免费软件可以是专有软件。

在自由中自由意味着社区控制。

什么是社区控制? 由基金会运营的项目? 所以你会认为 VS Code、Atom 编辑器和 Ubuntu 是非自由软件吗? 那么你的定义与 FSF、EFF 和许多其他组织提出的定义有很大不同。

我同意 Docker Inc 没有积极与社区讨论这个问题,但这与“自由如自由”无关。

抱歉,各位,我们不要在问题跟踪器上进行此类讨论。

我同意 Docker Inc 在这个问题上没有积极与社区讨论

我们可以通过docker build支持您想要的任何构建格式。 “官方” Dockerfile 格式不支持此选项,但这并不意味着docker build不能使用它。
查看https://matt-rickard.com/building-a-new-dockerfile-frontend/作为构建与docker build一起使用的自定义前端的示例。
请注意,此前端是一个示例,说明您可以如何执行与 Dockerfile 格式完全不同的操作,但这不是必需的。 如果愿意,您可以采用现有的 Dockerfile 格式并添加自己的功能。

至于在官方 Dockerfile 格式中添加一些东西......我会说总是欢迎建议,格式在https://github.com/moby/buildkit 中维护
但请记住,每一个新功能都意味着维护工作的新负担,包括经常限制未来可以做的事情。

我认为很可能组合多个 Dockerfile 的许多用例实际上可以通过 Dockerfile 中的新功能来解决……特别是从任意图像中获取COPY --fromRUN --mount

如果这个假设的 INCLUDE 可以创建额外的容器作为实现细节,而我不必给出 @#$%,那么它将大大减少围绕可组合容器的隐含和狡猾的销售宣传的挫败感。 我真的只想回到应用程序并交付功能。 抱歉给您带来不好的感觉,但我是 docker/container noob,遇到了许多其他海报已经表达的相同困惑。

如果你可以这样做:

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   custom image (with both python and rust)
             \                                 /
              \----- rust:1.44-alpine3.12 ----/

_注意两个图像都是同一图像的后代。 这是关键!_

就这么简单:

FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

_与使用“COPY --from image”指令(多阶段构建)相比,您不必考虑实现细节(要复制哪些文件/环境变量)。_

如果您想合并图像,现在的样子

FROM alpine:3.12.0

# INCLUDE rust:1.44-alpine3.12
COPY --from=rust:1.44-alpine3.12 / /
ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=1.44.1

# INCLUDE python:3.8.3-alpine3.12
COPY --from=python:3.8.3-alpine3.12 / /
ENV PATH /usr/local/bin:$PATH
ENV LANG C.UTF-8
ENV GPG_KEY E3FF2839C048B25C084DEBE9B26995E310250568
ENV PYTHON_VERSION 3.8.3
ENV PYTHON_PIP_VERSION 20.1.1
ENV PYTHON_GET_PIP_URL https://github.com/pypa/get-pip/raw/eff16c878c7fd6b688b9b4c4267695cf1a0bf01b/get-pip.py
ENV PYTHON_GET_PIP_SHA256 b3153ec0cf7b7bbf9556932aa37e4981c35dc2a2c501d70d91d2795aa532be79

_ENV 指令是从这些镜像的 Dockerfiles 中复制粘贴的。_


这也将允许更好的容器重用,并使将可能需要很长时间才能编译或构建自己的东西放在一起变得非常容易!

考虑到使用这种方法,程序只需为每个平台/基础映像版本编译一次 - 并且更容易重用,而不是自己实现。 试想一下,由于缺乏一个好的/通用的包管理器,在 C++ 中“轮子已经被重新实现了多少次”。 我们是否希望 Docker 出现类似的情况?

@bergkvist ,见https://github.com/moby/moby/issues/3378#issuecomment -381449355 和https://github.com/moby/moby/issues/3378#issuecomment -381641675。

在我看来,您提出的任何解决方案都与图表不符。 相反,你正在做:

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   \
             \                                   \
              \----- rust:1.44-alpine3.12 --------\ custom image 

因此,任何在rust中修改过的文件都会被python覆盖。 组合它们而不复制另一个需要一些合并。

@eine是的,如果发生冲突,文件将被覆盖。 这是真的。 因此,对称的图形将是没有(相关)文件重叠的特殊情况。 你这个图的版本比较一般。

我关于让两个图像都继承自同一个完全图像的观点是,发生严重冲突的可能性可能很小。

我想可能会出现一些与包管理器文件相关的冲突。 如果两个图像都使用包管理器来安装不同的东西。 我不确定是否还有其他“常见冲突”可以通过某种特殊情况处理。

合并两个文件绝非易事。 我认为在一般情况下,覆盖可能比试图变得聪明更好。 至少这样当事情不工作时更容易调试。

4天前在这里发表过评论,决定学习Golang,研究一下moby/buildkit代码的前端代码。

我现在已经创建了一个自定义前端,它接受我上面讨论的 INCLUDE 语句。

#syntax=bergkvist/includeimage
FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

要使用自定义语法,请记住在构建时设置 DOCKER_BUILDKIT=1。

DOCKER_BUILDKIT=1 docker build -t myimage .

代码可在此处获得: https :
以及 Docker Hub 上的图像: https :

此页面是否有帮助?
0 / 5 - 0 等级