我该如何从零开始构建Docker镜像?

6

我已经有一些Docker的经验了,但是我建立的所有镜像都是基于其他镜像的。

我仍然不知道第一个Docker镜像是从哪里来的?
换句话说,如果我需要一个特定的镜像,比如Ubuntu,它与官方镜像差别很大,该怎么办?

20180928更新:
根据目前的回答和评论,似乎scratch是最初的镜像。每个镜像都是从这个镜像构建而来的。所以问题来了:什么是scratch?你们能用通俗易懂的语言解释一下吗?

20180929更新:
根据评论中链接提供的信息,确实,构建FROM scratch的镜像(例如,light/hello:latest)没有额外的文件,只有我们添加的文件。从light/hello:latest启动容器后,会出现除我们添加的文件之外的更多文件和目录。

现在我知道了,因为每个容器都必须有一个用于执行的根文件系统,所以这些额外的文件和目录是由容器运行时实现(runC/libcontainer)基于runC libcontainer规范v1创建的,该规范遵循OCI runtime规范。

现在回到我的困惑:什么是scratch?它是Docker保留的一些技巧吗?就像Java项目总是从一个主函数开始:public static void main(String[] args)

20181008更新:
现在我认为我应该首先弄清楚Docker镜像到底是什么。这怎么做呢?如果可能和必要,您可以在这里放一些源代码。请给我一些线索。

提前感谢您的帮助。


https://hub.docker.com/_/scratch/ 和 https://github.com/tianon/docker-brew-ubuntu-core/blob/222130dfdfa777c09a17b3f08ba68c5b9850e905/xenial/Dockerfile 可能会有所帮助。 - atline
2个回答

8

基础镜像没有Dockerfile中的FROM语句或使用FROM scratch命令构建。

父镜像是您的镜像所基于的镜像。它指的是Dockerfile中的FROM命令内容。

使用scratch创建简单的父镜像

您可以使用Docker预留的最小镜像scratch作为构建容器的起点。使用scratch "镜像"向构建过程发出信号,表示您希望Dockerfile中的下一个命令成为镜像中的第一层文件系统。

尽管scratch出现在Docker Hub的存储库中,但您无法拉取它、运行它或将任何镜像标记为scratch。相反,您可以在Dockerfile中引用它。例如,使用scratch创建最小的容器:

FROM scratch
ADD hello /
CMD ["/hello"]

假设您按照https://github.com/docker-library/hello-world/中的说明构建了可执行文件“hello”,并且使用-static标志进行了编译,您可以使用以下docker build命令构建此Docker映像:
docker build --tag hello .

从零开始 一个明确为空的镜像,特别用于构建“FROM scratch”镜像

这个镜像最有用的是在构建基础镜像(如debian和busybox)或超小型镜像(仅包含单个二进制文件及其所需内容,例如hello-world)的上下文中。

scratch不会向您的Docker镜像添加层。但为什么要使用scratch呢?因为

必须为容器提供根文件系统以进行执行。容器将使用此根文件系统(rootfs)来监禁并在其中生成进程,其中二进制文件和系统库位于该目录内。任何要执行的二进制文件都必须包含在此rootfs中。

develop-images baseimages


请问您能否添加更多关于Scratch的信息?它到底是什么?一堆文件和目录吗?我只想知道最终的结果。 - Light.G
非常有用的链接信息,非常感谢。我正在尝试用更通俗的语言对其进行总结,你也想这样做吗? - Light.G

2
代替从服务器或分发镜像基础中获取,Dockerfile可以声明自己从"scratch"开始。"scratch"是一个特殊的镜像名称,它不包含任何东西——没有文件,没有目录,甚至没有镜像层。
最常见的使用FROM scratch的方法是围绕一个静态编译的二进制文件(通常在Go中,也可能在C/C++中,但在需要解释器的语言如Java或Python中不可能)创建一个非常小的镜像。这可能看起来像:
FROM scratch
COPY app /
ENTRYPOINT ["/app"]

如果您以某种方式查看该图像,则只会看到单个文件/app和几个注入的系统位(例如,我认为您始终会获得/dev/proc)。这很棘手,因为您无法运行任何shell(除非您显式创建一个/bin目录)。
“scratch”出现的另一个地方是在基础映像中,例如像此debian:stable Dockerfile中:
FROM scratch
ADD rootfs.tar.xz /
CMD ["bash"]

再次强调,从零开始,解压缩Debian安装的tar文件,并将其用作未来工作的起点。

谢谢你的回答。难怪我无法使用shell脚本运行容器。根本没有bash... - Light.G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接