ekk*_*kis 78 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这样的依赖关系,为了运行我的图像,调用上下文必须首先安装它需要的图像?
我糊涂了...
Nag*_*gev 98
我总结一下我对问题和答案的理解,希望对其他人有用。
\n问题:让\xe2\x80\x99s 说我有三个图像:apple、Banana和Orange。我可以有一个包含FROM apple
,的 Dockerfile ,FROM banana
它FROM orange
会告诉 docker 神奇地将所有三个应用程序合并到一个映像(包含三个单独的应用程序)中,我可以将其称为smoothie吗?
回答:不,你不能。如果这样做,您最终将得到四个图像,即您拉出的三个水果图像,加上基于最后一个FROM
图像的新图像。例如,如果FROM orange
Dockerfile 中的最后一条语句没有添加任何内容,则Smoothie图像将只是橙色图像的克隆。
典型的 docker 映像将包含应用程序运行所需的几乎所有内容(不包括内核),这通常意味着它们\xe2\x80\x99 是根据其所选操作系统和特定版本或发行版的基础映像构建的。
\n可以理解的是,在不考虑所有可能的发行版、文件系统、库和应用程序的情况下成功合并镜像并不是 Docker 想要做的事情。相反,开发人员应该拥抱微服务范例,运行多个容器,根据需要相互通信。
\n图像合并的一种可能的用例是将 Linux 发行版与我们所需的应用程序(例如 Ubuntu 和 Node.js)混合搭配。这不是解决方案:
\nFROM ubuntu\nFROM node\n
Run Code Online (Sandbox Code Playgroud)\n如果我们不想坚持使用应用程序映像选择的 Linux 发行版,我们可以从我们选择的发行版开始,并使用包管理器来安装应用程序,例如
\nFROM ubuntu\nRUN apt-get update &&\\\n apt-get install package1 &&\\\n apt-get install package2\n
Run Code Online (Sandbox Code Playgroud)\n但你可能已经知道了。通常,所选发行版中没有\xe2\x80\x99可用的快照或软件包,或者\xe2\x80\x99不是所需的版本,或者它在开箱即用的 docker 容器中无法正常工作,这就是想要使用图像的动机。I\xe2\x80\x99m 只是确认,据我所知,如果您真的想遵循单一方法,唯一的选择就是长期这样做。
\n以Node.js为例,您可能需要手动安装最新版本,因为apt
它提供了一个古老的版本,并且snap
不附带 Ubuntu 映像。对于Neo4j,我们可能需要根据文档和许可证下载该包并手动将其添加到映像中。
如果大小不重要,一种策略是从最难手动安装的基本映像开始,然后将其余的添加到顶部。
\n还可以选择使用多个FROM
语句并在构建阶段之间或将内容手动复制到最终阶段。换句话说,如果您知道自己在做什么,则可以手动合并图像。根据文档:
\n\n\n
AS name
(可选)可以通过在指令中添加\n来为新的构建阶段指定名称FROM
。该名称可以在后续指令中使用FROM
,\nCOPY --from=<name>
来引用此阶段构建的映像。
就我个人而言,我\xe2\x80\x99d只习惯将这种合并方法与我自己的图像一起使用,或者遵循应用程序供应商的文档,但如果您需要它或者您只是感到幸运,它\xe2\x80\x99s就在那里。
\n不过,这种方法的一个更好的应用是,当我们确实想要使用来自不同图像的临时容器来构建或执行某些操作并在复制所需的输出后将其丢弃时。
\n我想要一个精简映像gpgv
,并且基于此Unix & Linux 答案,我安装了整个映像gpg
,yum
然后仅将所需的二进制文件复制到最终映像:
FROM docker.io/photon:latest AS builder\nRUN yum install gnupg -y\n\nFROM docker.io/photon:latest\nCOPY --from=builder /usr/bin/gpgv /usr/bin/\nCOPY --from=builder /usr/lib/libgcrypt.so.20 /usr/lib/libgpg-error.so.0 /usr/lib/\n
Run Code Online (Sandbox Code Playgroud)\n其余的Dockerfile
继续照常进行。
Von*_*onC 87
什么是基本形象?
一组文件,加上EXPOSE
'd端口,ENTRYPOINT
和CMD
.
您可以添加文件并基于该基本图像构建新图像,使用新Dockerfile
的FROM
指令开头:后面提到的图像FROM
是新图像的"基本图像".
这是否意味着如果我
neo4j/neo4j
在一个FROM
指令中声明,当我的图像运行时,neo数据库将自动运行并在端口7474上的容器中可用?
只有你没有覆盖CMD
和ENTRYPOINT
.
但是图像本身就足够了:FROM neo4j/neo4j
如果必须添加与neo4j
您的特定用法相关的文件,则可以使用neo4j
.
FROM
可以在单个Dockerfile中多次出现
别:有提议删除该"功能"无论如何(issue 13026)
问题14412提到:
使用multiple
FROM
并不是一个真正的功能,而是一个bug(哦,极限很紧,FROM
Dockerfile中的多个用例很少).
2017年5月更新(18个月后),码头(moby)17.05-ce.
多个FROM 可以在单个Dockerfile中使用.
请参阅" 生成器模式与Docker中的多阶段构建 "(Alex Ellis)和TõnisTiigi的PR 31257.
之前:
构建器模式涉及使用两个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 .
Run Code Online (Sandbox Code Playgroud)
相同(!)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"]
Run Code Online (Sandbox Code Playgroud)
结果将是两个图像,一个用于构建,一个仅用于生成的应用程序(更多,更小)
REPOSITORY TAG IMAGE ID CREATED SIZE
multi latest bcbbf69a9b59 6 minutes ago 10.3MB
golang 1.7.3 ef15416724f6 4 months ago 672MB
Run Code Online (Sandbox Code Playgroud)
Eva*_*oll 19
第一个答案对我的口味来说太复杂、太具有历史意义且没有信息量。
其实很简单。Docker 提供了一种称为多阶段构建的功能,这里的基本思想是,
让我们从第一个开始。很多时候你会看到像 Debian 这样的东西。
RUN apt-get update \
&& apt-get dist-upgrade \
&& apt-get install <whatever> \
&& apt-get clean
Run Code Online (Sandbox Code Playgroud)
我们可以根据上述内容来解释所有这些。上面的命令链接在一起,因此它表示不需要中间图像的单个更改。如果是这样写的
RUN apt-get update ;
RUN apt-get dist-upgrade;
RUN apt-get install <whatever>;
RUN apt-get clean;
Run Code Online (Sandbox Code Playgroud)
这将导致 3 个更多的临时中间图像。将其缩减为一张图像后,还存在一个问题:apt-get clean
不清理安装中使用的工件。如果 Debian 维护者在他的安装中包含一个修改系统的脚本,该修改也将出现在最终解决方案中(请参阅类似pepperflashplugin-nonfree
示例)。
通过使用多阶段构建,您可以获得单个更改操作的所有好处,但它需要您使用COPY --from
此处记录的语法手动将临时映像中引入的文件列入白名单并复制。此外,这是一个很好的解决方案,没有替代品(如apt-get clean
),否则您的最终图像中将有很多不需要的文件。
也可以看看
FROM
这可能是使用多个(又名多阶段构建)的最基本用例之一。
我想要一个 dockerfile,并且我想更改一个单词,根据我设置该单词的内容,我会根据是否要运行、开发或发布应用程序获得不同的图像!
运行- 我只想运行该应用程序
开发- 我想编辑代码并运行应用程序
发布- 在生产环境中运行应用程序
假设我们在 dotnet 环境中工作。这是一个 Dockerfile。如果没有多阶段构建,将会有多个文件(构建器模式)
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/runtime:5.0 AS base
WORKDIR /app
FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ConsoleApp1/ConsoleApp1.csproj", "ConsoleApp1/"]
RUN dotnet restore "ConsoleApp1/ConsoleApp1.csproj"
COPY . .
WORKDIR "/src/ConsoleApp1"
RUN dotnet build "ConsoleApp1.csproj" -c Release -o /app/build
FROM build AS publish
RUN dotnet publish "ConsoleApp1.csproj" -c Release -o /app/publish
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ConsoleApp1.dll"]
Run Code Online (Sandbox Code Playgroud)
想要运行该应用程序吗?保留FROM base AS final
上面 dockerfile 中的当前位置。
想要在容器中开发源代码吗?将同一行更改为FROM build AS final
想要发布到产品中吗?将同一行更改为FROM publish AS final
归档时间: |
|
查看次数: |
73047 次 |
最近记录: |