赞
踩
还可参考 并非每个容器内部都能包含一个操作系统
结论:
操作系统是管理计算机硬件、软件资源,并为计算机程序提供通用服务的系统软件。
而管理硬件、软件资源,都是由内核实现的。docker镜像是不含内核的,容器与宿主机共享内核。docker镜像只包含一部分提供通用服务的用户态(userland),如各种lib、系统应用,还有一部分服务由内核提供。
docker镜像是否包含操作系统?我这里尝试一次过给大家整明白。可能内容稍微多点,烦请诸君给点耐心,应该不会让你失望的。
首先,这里先给出我认为正确的答案:完全不包含或者包含操作系统部分内容!
首先,这里要搞清楚操作系统是怎么组成的。操作系统实现原理往深说的话会涉及到操作系统很多的实现细节,往简单点来说的话,我们可以将操作系统简单理解为由两层嵌套的软件组成的。
而上面说的部分包含,说的就是包含这里应用层的部分工具或者rootfs,即/etc/之类的。
下面我们通过示例来证明这两种情况。
要证明一个docker镜像中不包含任何操作系统相关的东西,思路很简单,我们创建一个最简单的hello world应用,然后编写Dockerfile,文件不要引入任何其他层的文件系统,而是直接基于scratch这个空镜像,然后把我们的hello world应用打包进去,最后看它是否能跑起来就可以了。
我们这里用go语言来写个简单的代码
- // main.go
- package main
-
- import "fmt"
-
- func main() {
- fmt.Println("Hello World")
- }
然后通过以下命令构建可执行程序
- $ GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o hello
- $ file hello
- > hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked
什么是空镜像
跟着创建Dockerfile来打包镜像,注意这里我们FROM中填写的是上面说的scratch这个空镜像,而不是debian什么的。也就是说最终这个容器里面只有一个/文件夹,下面只有一个hello,且运行是直接执行命令/hello来在该容器内运行该应用
- FROM scratch
- COPY hello /
- CMD ["/hello"]
构建hello镜像并运行容器
- $ docker build -t hello .
- $ docker run hello
- > Hello World
从输出中我们可以看到应用如预期般运行起来并正常输出。那么下一步,我们就是去证明这个容器里面确实没有包含操作系统任何的东西。
思路很简单,我们通过第三方工具来查看hello这个镜像的分层文件系统。看下里面有没有包含操作系统rootfs之类的任何操作系统相关的文件夹或者文件。
这里我用的是dive这个工具,输出如下(执行dive hello的输出):
很明显,整个镜像里面只有一个文件hello,不包含任何其他内容,更别说包含任何操作系统了!不信的话我们可以试下在镜像中执行个bash。
file not found,证明完毕!
其实证明了上面说的镜像可以不包含任何操作系统,依然能正常把应用在容器中运行起来,也从另一个侧边说明,我在镜像中可以添加任何内容,并不影响我的hello能正常运行。而事实上,有些流行的应用往往需要用到很多操作系统用户层提供的库才能正常运作,比如我们下面分析的nginx镜像,里面就用了debian的rootfs文件系统。
$ docker run -d -P --name nginx nginx:latest
我们同样通过上面的dive工具来对nginx镜像进行分析(dive nginx输出)
从上面的输出,我们第一感觉这里面就是某个linux发行版的根文件系统内容。我们去看下它的Dockerfile:
- FROM debian:buster-slim
-
- LABEL maintainer="NGINX Docker Maintainers <docker-maint@nginx.com>"
-
- ENV NGINX_VERSION 1.17.10
- ENV NJS_VERSION 0.3.9
- ENV PKG_RELEASE 1~buster
- ...
看上去应该是基于debian的发行版。那么这里包含了debian的多少东西呢?
这了我们再去看下debian:buster-slim对应的Dockerfile:
- FROM scratch
- ADD rootfs.tar.xz /
- CMD ["bash"]
很明显,这里面也是基于scratch这个空镜像,但是在这基础上加入了debian的rootfs,注意这里并没有加入kernel等的内容,仅仅只是根文件系统而已。
这也就证明了我们上面说的Docker镜像可以报包含操作系统部分内容的说法,而在这里,部分内容指的就是debian发行版的根文件系统。
证明完毕!
从上面的分析我们可以看到,一个Docker的镜像其实本来可以不包含任何东西的。Docker容器本身也就是一个独立进程(组)而已。我们一开始只是想通过Linux内核底层的namespaces把这个进程隔离开来以防影响其他进程或者被其他进程影响,通过cgroup来限制其资源的使用而已。
但是到了后来,大家发现可以把各种不同Linux发行版的rootfs加入到镜像中作为基础镜像,通过简单的docker run -it fedora bash 之类的命令就能愉快的玩耍不同的发行版。且有了这些基础设施后,如nginx这些应用就很容易的在容器上跑起来。
我想这也就是为什么后来出现的很多镜像都是基于一些Linux发行版rootfs的,从而让一些不明觉厉的朋友们误以为docker镜像是包含了各种linux操作系统的发行版了!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。