我是新手,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)不同的概念感到困惑。当我运行从包含FROM alpine:3.7
在其中的图像构建的 docker 容器时会发生什么Dockerfile
?运行 alpine Linux 的虚拟机是否在运行 debian 的物理 PC 上启动?
如果我想做一些非常原始的事情——比如ls
——在我的 docker 容器中,如何选择最小的基础镜像?我随机选择了 alpine——不是特别清楚自己在做什么——什么时候需要选择不同的发行版,比如 ubuntu 等?
Docker 镜像就像文件系统。一个 docker 映像将是一个包含 Alpine、Ubuntu、Arch Linux 安装的磁盘......即使您的主机是 Debian。(你也可以有 Debian 的图像,或者不同版本的图像,但如果它们完全不同,则更容易解释)
这里的诀窍是您在所有这些中运行相同的内核。Docker 是一个容器解决方案。您的基于 alpine 的机器将在 Debian 分发的 Linux 内核上运行(受 docker 限制,无法看到外部世界)。Alpine 将与任何足以运行 docker 的新 Linux 内核一起愉快地工作,因此它就像您安装了 Alpine(或 Ubuntu,或 Arch Linux...)一样工作。
缺点是你不能在那里运行 BSD 或 Windows,因为它们的用户空间不能使用 Linux 内核运行。另外很明显,他们需要使用兼容的架构。
您启动一个新容器,该容器基于 alpine 安装启动映像,这与启动 Alpine 安装非常相似。
请注意,您可以创建一个 docker 实例来执行其他操作,例如启动一个 bash 控制台供您使用,而不是启动发行版通常在启动时运行的守护进程。
如果您希望能够运行
ls
,并且仅此而已,则可以创建仅包含的图像ls
(因为它需要 libc,最好作为 的副本busybox-static
)。不过,这可能有点矫枉过正。Alpine 经常用于此目的,因为它是一个非常小的发行版。
如果您需要该发行版提供的东西。假设您想运行一个控制台程序,其依赖项声明为“需要来自 Ubuntu MN 的包 X、Y 和 Z”。因此,在基于“Ubuntu MN”图像的 docker 实例上运行它是有意义的。
当您在 Debian 主机上工作时,您可能更愿意使用 Debian 映像,并且将您的 docker 映像基于 Debian 是有意义的。
这相当于“我需要安装一个新的 GNU/Linux 服务器,我应该使用哪个发行版?”这个问题,这最终将是个人(或团队)在众多好的选项中的个人选择。
我认为你的问题实际上是“我为什么需要这个”,简单的答案是“因为它必须是独立的”。请记住,当容器运行时,其中的任何内容都无法访问主机文件系统。
这是一个问题,因为许多程序需要共享库。让我们来看看
echo
:所以即使是简单的程序
echo
也不是独立的。这取决于 libc。如果我要创建一个只包含二进制文件的FROM scratch
Docker 映像echo
,它就无法运行。当然,您可以(重新)编译一些软件以进行静态链接,但这需要时间。有时您还依赖于其他东西,例如根证书,让已建立的发行版处理它更容易。
当你启动一个容器时,它不会“运行容器操作系统”。相反,在大多数更简单的容器中,只启动一个进程(如命令行或 中所定义
Dockerfile
)。更复杂的容器倾向于使用自己的“init”系统,因为经典的 OS 初始化系统通常不适合在容器中使用。选择合适的基础图像不是可以形式化的。您需要考虑需求,并且需要研究可用的内容。真的没有办法解决这个问题。您也可能有个人喜好。对于这种特殊情况,busybox图像可能是合适的并且非常少。
使用不同类型的容器软件(LXC/LXD),您实际上可以在容器中运行整个第二个 Linux 发行版,带有常规的 init 系统和诸如此类的东西。如果不需要那么多隔离,这比完全虚拟化更可取。它提供了非常出色的性能,就像 Docker 一样。
使用 Linux 命名空间的隔离足以让许多发行版共享相同的运行内核。但是将其视为轻量级虚拟机是有道理的。