上一篇文章已经讲述了为什么会有Docker容器的出现,其实本质上来说,Docker是代码和操作系统之间的中间层,为了解决程序员“这个程序在我的电脑上明明能跑,为什么到你那就不行了呢”的问题。科学家们选择将程序环境(依赖库和配置)一起打包给到对方运行,而这个打包并运行的工具软件,就是Docker,接下来我们看看它具体是怎么实现的

基础镜像

既然环境不同会导致运行结果不同,那么我们首先要做的事情就是统一环境。而环境中最重要的就是操作系统。我们得让所有程序都跑在同一个操作系统上,但是如果打包整个操作系统,那空间未免需要占用的太多,但是我们又知道,操作系统分为用户空间和内核空间,并且应用程序都是运行在用户空间的,这不就解决了,我们完全可以阉割操作系统,只要操作系统的用户空间部分,就能构建我们想要的环境。

其次我们需要统一语言,即程序语言依赖,我们要跑python,好歹得装个python解释器吧;要跑JAVA应用,得装个JVM吧。所以,程序语言依赖也是必不可少的一项

我们选中一个基础的操作系统和程序语言后,我们将它们对应的文件系统,依赖库,配置等放在一起打包成压缩包似的文件,这就是所谓的基础镜像

image-20240415112709356

Dockerfile是什么

单纯有基础镜像显然是不够的,我们经常还需要安装一些依赖,比如gcc等,甚至还要创建一些文件夹,才能运行我们的应用程序。linux中,所有的命令都通过命令行实现,所以有了基础镜像后,我们还需要用命令行将依赖装好,这时候,我们可以将所需要的命令一行行地列出来,就像一份To Do List,意思是要求在基础镜像的基础上按着 To Do List挨个执行命令,比如下面的To Do List

# 指定基础镜像
FROM python:3.9

# 设置工作目录
WORKDIR /app

# 复制依赖文件到容器中
COPY requirements.txt .

RUN yum install gcc
# 安装依赖
RUN pip install --no-cache-dir -r requirements.txt

# 将当前目录下的所有文件复制到容器的 /app 目录下
COPY . /app

# 设置容器启动时执行的命令
CMD ["python", "app.py"]

像这样一份列清楚了从操作系统到应用服务启动,需要做哪些事情的清单文件,就叫做Dockerfile,大家在用pip安装其他github代码时,也会有pip install -r requirements.txt,这里的requirements.txt和Dockerfile作用一致

容器镜像是什么

Dockerfile只是描述了要做哪些事,并没有真正开始做,当我们执行Docker Build的时候,Docker软件就会按着Dockerfile的说明,一行行构建环境和应用程序,最终这个环境+程序被打包成压缩包,放在一个叫容器镜像的东西中

只要将容器镜像传到任意一台服务器上,对这个镜像进行“解压缩”,我们就可以运行环境和程序,通常使用docker run xxxx的命令进行运行

Registry是什么

为了使每个人都能更快捷的获取镜像,如果挨个传输过去,那么所有的压力都给到网络带宽了,这显然是不合理的。我们可以参考github代码仓库的做法,所有人用git push上传自己的代码到github上,再用git pull从github上拉取到自己的机器上。Docker也一样,通过docker push将镜像推到仓库,在需要的时候通过docker pull将镜像拉取到机器上,这个负责管理镜像仓库推拉能力的服务,就叫Docker Registry

容器是什么

解决了服务器中间的容器镜像传输问题我们可以执行docker pull到自己的服务器上,然后执行docker run,将这个镜像解压缩,获得一个独立的环境和应用程序并运行起来,这样独立的环境和程序,就是一个容器,一个操作系统可以跑多个容器,不同的容器之间是相互隔离互不干扰的,以下是我服务器上运行的几个基础docker容器

image-20240705175245532

现在我们可以来讨论一下虚拟机和容器的区别。虚拟机和容器很像,都可以独立运行彼此互不干扰,但是不同的是,传统虚拟机自带一个完整的操作系统,而容器本身不带完整操作系统,容器的基础镜像实际上只包含了操作系统的核心依赖库和配置文件等组件。它利用一个叫Name Space的能力让它看起来像是一个独立的操作系统,再利用一个叫Cgroup的能力限制它使用的计算机资源。

综上所述,容器本质上只是一个自带独立运行环境的特殊进程,底层用的实际上是宿主机的操作系统内核

总结

Docker本质上就是一个将程序和环境打包并运行的工具软件,而Docker容器本质上只是一个自带独立运行环境的特殊进程,底层用的其实是宿主机的操作系统内核

Docker软件通过Dockerfile描述环境和应用程序的依赖关系,docker build构建镜像,docker pulldocker push实现和Docker Registry交互实现存储和分发镜像,docker run用于启动容器

Docker能够帮助程序员更好地解决环境配置问题,不需要程序员在环境配置上花太多的时间和精力,Docker Compose解决的是多个容器组成的一套服务的部署问题,Docker Swarm解决的是多个容器组成的一套服务在多台服务器上的部署问题,k8s是Docker Swarm的竞品,在更高维度上兼容了Docker容器,实现容器的编排和调度,k8s除了支持Docker的容器外,还支持其他的容器