如何拥有不同操作系统的 docker 镜像层

如何拥有不同操作系统的 docker 镜像层

我对此还很陌生docker,正在尝试通过从头开始的示例来更好地理解它。

我想从我能想到的最简单的方式开始:从我的语境到我的docker镜像的根目录,然后验证文件在容器中的存在。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 9.8 (stretch)
Release:        9.8
Codename:       stretch
$ ls -R
.:
demo.txt Dockerfile
$
$ cat Dockerfile
FROM scratch
WORKDIR .
COPY demo.txt /foo
$ 
$ docker build -t demo:v1 -f ./Dockerfile .
Sending build context to Docker daemon  28.67kB
Step 1/3 : FROM scratch
 --->
Step 2/3 : WORKDIR .
 ---> Using cache
 ---> 8eb9da711a99
Step 3/3 : COPY demo.txt /foo
 ---> c57e0e9a316b
Successfully built c57e0e9a316b
Successfully tagged demo:v1
$
$ docker run -it demo:v1 ls -l /foo
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"ls\": executable file not found in $PATH": unknown.

我理解问题的要点:FROM scratch就是那样 -- 甚至没有ls。因此,可以通过更改FROM scratch为更有意义的内容来解决:

$ cat Dockerfile
FROM alpine:3.7
WORKDIR .
COPY demo.txt /foo
$ 
$ docker build -t demo:v1 -f ./Dockerfile .
Sending build context to Docker daemon  28.67kB
Step 1/3 : FROM alpine:3.7
 ---> 6d1ef012b567
Step 2/3 : WORKDIR .
 ---> Using cache
 ---> 51c22fe2fd60
Step 3/3 : COPY demo.txt /foo
 ---> Using cache
 ---> e2c241241653
Successfully built e2c241241653
Successfully tagged demo:v1
$ 
$ docker run -it demo:v1 ls -l /foo
-rw-r--r--    1 root     root             6 Sep  8 23:42 /foo

这让我想到了一个问题:我对安装/运行与主机 (debian) 上不同的 Linux 发行版 (alpine) 的概念感到困惑。当我运行从其包含的映像构建的 docker 容器时会发生什么FROM alpine:3.7Dockerfile运行 alpine Linux 的虚拟机是否在运行 debian 的物理 PC 上启动?

如果我想ls在我的 docker 容器中做一些非常原始的事情,那么如何选择最小的基础镜像?我随机选择了 alpine —— 并不特别清楚自己在做什么 —— 什么时候需要选择不同的发行版,比如 ubuntu 等?

答案1

我认为你的问题实际上是“我为什么需要这个”,简单的答案是“因为它必须是独立的”。请记住,当容器运行时,其中的任何东西都无法访问主机文件系统。

这是一个问题,因为许多程序都需要共享库。让我们来看看echo

~$ ldd $(which echo)
        linux-vdso.so.1 (0x00007fffeec73000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1a57c80000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f1a57e75000)

因此,即使是像 这样的简单程序echo也不是自包含的。它依赖于 libc。如果我只创建一个FROM scratch包含二进制文件的 Docker 映像echo,它就无法运行。当然,你可以(重新)编译一些软件以进行静态链接,但这需要时间。

有时您还依赖于其他东西,例如根证书,而让已建立的发行版来处理它会更容易。

当你启动一个容器时,它会不是“运行容器操作系统”。相反,在大多数较简单的容器中,只启动一个进程(如在命令行或 中定义Dockerfile)。更复杂的容器倾向于使用自己的“init”系统,因为经典的操作系统 init 系统通常不适合在容器中使用。

选择合适的基础镜像并不是可以正式确定的事情。您需要考虑需求,并研究可用的镜像。这真的没有办法解决。您也可能有个人偏好。对于这种特殊情况,也许忙碌箱图像很合适并且非常简约。


使用不同类型的容器软件 (LXC/LXD),您实际上可以在容器中运行整个第二个 Linux 发行版,包括常规初始化系统和其他东西。如果不需要那么多隔离,这比完全虚拟化更可取。它提供非常优越的性能,就像 Docker 一样。

使用 Linux 命名空间进行隔离足以让许多发行版共享同一个正在运行的内核。但将其视为轻量级虚拟机也有一定的道理。

答案2

Docker 镜像就像文件系统。Docker 镜像是一个包含 Alpine、Ubuntu、Arch Linux 安装的磁盘……即使您的主机是 Debian。(您也可以拥有 Debian 的镜像,或者不同版本的镜像,但如果它们完全不同,则更容易解释)

这里的诀窍是,你在所有容器中运行相同的内核。Docker 是一个容器解决方案。您的基于 alpine 的机器将在 Debian 分发的 Linux 内核上运行(受 docker 限制,无法看到外部世界)。Alpine 可以与任何足够新的 Linux 内核一起顺利运行 docker,因此它就像您安装了 Alpine(或 Ubuntu、Arch Linux...)一样工作。

缺点是你不能在那里运行 BSD 或 Windows,因为它们的用户空间无法与 Linux 内核一起运行。另外,显然,它们需要使用兼容的架构。

当我运行由 Dockerfile 中包含 FROM alpine:3.7 的映像构建的 docker 容器时会发生什么?运行 debian 的物理 PC 上是否启动了运行 alpine Linux 的虚拟机?

您启动一个新容器,它将基于 alpine 安装启动一个映像,这与启动 Alpine 安装非常相似。

请注意,您可以创建一个执行其他操作的 docker 实例,例如启动一个 bash 控制台供您使用,而不是启动发行版通常在启动时运行的守护进程。

如果我想在 Docker 容器中执行一些非常简单的操作(例如 ls),那么如何选择最小的基础镜像?我随机选择了 alpine。

如果您希望能够运行,且仅运行,那么您可以创建一个仅包含(因为它需要 libc,因此最好将其作为 的副本)的ls图像。但这可能有点小题大做。lsbusybox-static

由于 Alpine 的分布非常小,因此经常用于此。

不太清楚自己在做什么——什么时候需要选择不同的发行版,比如 ubuntu 等

如果您需要该发行版提供的某些东西。假设您想要运行一个控制台程序,其依赖项声明为“需要来自 Ubuntu MN 的包 X、Y 和 Z”。因此,在基于“Ubuntu MN”映像的 docker 实例上运行它是有意义的。

由于您在 Debian 主机上工作,因此您可能更喜欢使用 Debian 映像,并且将您的 docker 映像基于 Debian 映像是有意义的。

这相当于这个问题“我需要安装一个新的 GNU/Linux 服务器,我应该使用哪个发行版?”,这最终将是个人(或团队)在众多好的选择中做出的个人选择。

相关内容