多个FROM-含义


112

我想在github上为Linkurious项目构建一个docker映像,这需要同时运行Neo4j数据库和Node.js。

我的第一种方法是为我的映像声明一个基本映像,其中包含Neo4j。参考文档未以任何有用的方式定义“基础图像”:

基本图像:没有父图像的图像是基本图像

从中我读到,如果该图像本身没有基础图像,则可能只有基础图像。

但是什么是基本图片?这是否意味着如果我在FROM指令中声明neo4j / neo4j,那么在运行映像时,neo数据库将自动运行并在端口7474的容器中可用?

阅读Docker参考(请参阅:https : //docs.docker.com/reference/builder/#from)我看到了:

FROM可以在单个Dockerfile中多次出现,以创建多个映像。只需在每个新的FROM命令之前记录一次提交输出的最后一个图像ID。

我想创建多个图像吗?似乎我想要的是拥有一个包含其他图像内容的单个图像,例如neo4j和node.js

我没有在参考手册中找到任何声明依赖项的指令。是否没有像RPM中那样的依赖关系,为了运行我的映像,调用上下文必须首先安装它需要的映像?

我很困惑...


注意:可能在2017年,你现在有多个FROMDockerfile。请参阅下面的我编辑过的答案。
VonC

看看是否找到我的答案更干净。如果是这样,请考虑接受。
Evan Carroll

Answers:


113

什么是基本图片?

一组文件,加上EXPOSE端口ENTRYPOINTCMD
您可以添加文件并基于该基础图像构建新图像,Dockerfile并以FROM指令开头:后面提到的图像FROM是新图像的“基础图像”。

这是否意味着如果我neo4j/neo4jFROM指令中声明,则在运行映像时,neo数据库将自动运行并且可在端口7474的容器中使用?

仅当您不覆盖CMD和时ENTRYPOINT
但是图像本身就足够了:FROM neo4j/neo4j如果您必须添加与neo4j的特定用途相关的文件,则可以使用neo4j

FROM 可以在一个Dockerfile中多次出现

:有一项建议无论如何都应删除该“功能”(问题13026

问题14412提到:

使用倍数FROM并不是真正的功能,而是一个错误(哦,很好,限制很严格,FROMDockerfile中很少有用例)。


使用docker(moby)17.05-ce更新2017年5月(18个月后)。

可以在单个Dockerfile中使用多个FROM 。
请参阅“ Builder模式与多阶段建立在泊坞 ”(由亚历克斯·埃利斯)和PR 31257通过TõnisTiigi

之前:

构建器模式涉及使用两个Docker映像-一个用于执行构建,另一个用于运送第一个构建的结果,而不会影响第一个映像中的构建链和工具。

后:

通用语法涉及FROM在Dockerfile中添加其他时间-以最后一条FROM语句为最终基础映像为准。要复制中间图像的伪像和输出,请使用COPY --from=<base_image_number>

Dockerfile的第一部分:

FROM golang:1.7.3 as builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html  
COPY app.go    .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

相同的(!)Dockerfile的第二部分:

FROM alpine:latest  
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app    .
CMD ["./app"]  

其结果将是两个图像,一个建筑,一个只有所产生的应用程序(很多,很多小)

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE

multi               latest              bcbbf69a9b59        6 minutes ago       10.3MB  
golang              1.7.3               ef15416724f6        4 months ago        672MB  

2
很遗憾删除多个FROM。在我看来,它最有用,尤其是在没有依赖机制的情况下。例如,对于RPM,我可以声明我的程序包需要另一个程序包才能运行,因此在安装时一切都为我设置。现实是,大多数事物都将需要多个依赖关系,因此在没有多个FROM的情况下,该如何工作?
ekkis,2015年

3
正如我在上一个答案(stackoverflow.com/a/33295292/6309)中提到的那样,@ ekkis是通过编排多个容器(每个容器提供一种特定的服务)并通过--link(docs.docker.com/用户指南/ dockerlinks /…)。
VonC

2
@VonC当然,在理想的情况下,拥有一个新的应用程序,并且可以理解所有模式。同时,我希望会有更多人尝试将其解决方案迁移到Docker,并且有无法通过网络解决的需求,例如软件依赖项,全部使用兼容的基础,但使用多个Dockerfile。相反,到目前为止,我能弄清的最好的办法是破解他们的Dockerfile来创建自己的Dockerfile。
Rainabba

@rainabba同意。遗留的巨石不会轻易迁移。趣闻:martinfowler.com/articles/...threedots.tech/post/microservices-or-monolith-its-detailhackernoon.com/...
VonC

2

第一个答案过于复杂,历史悠久,对我的口味没有帮助。


实际上很简单。Docker提供了一种称为多阶段构建的功能,这里的基本思想是:

  • 通过强迫您将想要的内容列入白名单,您不必手动删除不需要的内容,
  • 释放由于Docker的实现而将占用的免费资源。

让我们从第一个开始。很多时候,您会看到类似Debian的东西。

RUN apt-get update \ 
  && apt-get dist-upgrade \
  && apt-get install <whatever> \
  && apt-get clean

我们可以根据以上解释所有这些。上面的命令链接在一起,因此它代表单个更改,而无需中间映像。如果是这样写的

RUN apt-get update ;
RUN apt-get dist-upgrade;
RUN apt-get install <whatever>;
RUN apt-get clean;

这将导致另外3个临时中间图像。将其缩小为一个映像后,仍然存在一个问题:apt-get clean不清除安装中使用的工件。如果Debian维护者的安装中包含修改系统的脚本,则最终解决方案中还将包含修改内容(pepperflashplugin-nonfree有关示例,请参见类似内容)。

通过使用多阶段构建,您可以获得单个更改操作的所有好处,但它需要您使用COPY --from此处记录的语法手动将白名单并复制到临时映像中引入的文件。而且,这是一个很好的解决方案,没有其他选择(例如apt-get clean),否则最终映像中会有很多不需要的文件。

也可以看看


谢谢,但我看不到您如何解决我的问题。对我来说,FROM是一种继承机制,具有多个指令意味着我可以从多个父项继承。在您的回答中,您没有提及FROM或其他人利用软件打包的概念
ekkis,

1
也许那是混乱。FROM主要是名称空间声明。限定词更像是扩展而不是继承。您可以声明多个名称空间。这些名称空间中的每一个都可以扩展另一个名称空间。@ekkis如果其他答案对您有用,那么请务必坚持使用。
埃文·卡罗尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.