多个FROM - 意味着什么

时间:2015-10-24 18:58:49

标签: docker dockerfile

我想在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那样的依赖关系,为了运行我的图像,调用上下文必须首先安装它需要的图像?

我很困惑......

2 个答案:

答案 0 :(得分:70)

  

什么是基本形象?

一组文件,以及EXPOSE'd端口,ENTRYPOINTCMD
您可以添加文件并根据该基本图像构建新图像,使用以Dockerfile指令开头的新FROMFROM之后提到的图像是您的“基本图像”新形象。

  

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

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

  

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

不要:有提议删除该“功能”无论如何(issue 13026

Issue 14412提及:

  

使用多个FROM实际上不是一个功能,而是一个错误(哦,限制很严重,Dockerfile中多个FROM的用例很少。)

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

可以在单个Dockerfile中使用多个FROM Builder pattern vs. Multi-stage builds in Docker 查看“Alex Ellis”( PR 31257 )和Tõnis Tiigi

在:

  

构建器模式涉及使用两个Docker镜像 - 一个用于执行构建,另一个用于传送第一个构建的结果,而不会在第一个图像中受到构建链和工具的惩罚。

后:

  

一般语法涉及在Dockerfile中添加FROM个额外时间 - 最后一个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  

答案 1 :(得分:7)

第一个答案过于复杂,历史悠久,对我的口味而言毫无意义。


实际上很简单。 Docker提供了称为multi-stage builds的功能,此处的基本思想是

  • 通过强制您将所需的白名单列入白名单,从而使您不必手动删除不需要的内容,
  • 释放资源,否则这些资源会因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),否则最终映像中将有很多不需要的文件。

另请参见