Docker 容器技术讲解
容器本身并不是业务服务,而是一个用来承载和管理其他应用服务的工具。它可以把一个业务程序和它所需要的运行环境一起放进一个隔离的空间里,然后以容器进程的方式统一进行管理。这样做的好处是可以实现非常快速的启动、升级、回滚和销毁,极大地简化了运维工作。Docker 是目前最主流的容器引擎产品。
容器的主要作用就是把服务的控制和管理变得简单、轻量和标准化。使用容器之后,开发人员交付的是一个镜像,运维人员只需要在任意服务器上运行这个镜像,就可以得到完全一致的运行时环境。这解决了开发环境和生产环境不一致的问题,也降低了大规模部署的复杂度。
容器技术本质上是虚拟化技术的一种实现方式,但它和传统意义上的虚拟化有很大不同。虚拟化技术最早出现的原因是当年服务器的资源利用率非常低,很多时候一天中只有不到百分之二十的时间在工作,剩下的时间都在闲置。为了提高资源利用率,技术人员开始研究如何用软件去模拟硬件功能,让一台物理机可以同时运行多个操作系统,并且能够精细地分配 CPU、内存、磁盘、网络和 IO 等资源。在这个体系中,有一个非常重要的组件叫 Hypervisor,它负责管理系统资源,并把资源分配给不同的操作系统使用,同时保证它们之间相互隔离。
容器和传统虚拟机的关系就在于它们都是虚拟化,但层级不同。传统虚拟机是完整的操作系统,拥有独立的内核,而容器是直接运行在宿主机内核之上的。容器和宿主机共用内核,只是在用户空间层面做隔离。这也正是容器比虚拟机更轻量、启动更快的根本原因。
容器和虚拟机的区别是一个非常常见的问题。容器启动通常是秒级,而虚拟机是分钟级。容器占用空间小,属于轻量级,虚拟机占用空间大,属于重量级。容器之间是进程级隔离,虚拟机之间是内核级隔离。虚拟机的安全性更强,容器的安全性相对弱一些。容器扩展起来非常方便,而虚拟机扩展会比较麻烦。容器几乎没有额外的资源损耗,而虚拟机存在一定的性能损耗。两者的本质区别在于,虚拟机拥有完整的操作系统内核,而容器和宿主机共用同一个内核。从文件系统角度看,操作系统内核可以分为两部分,一部分是 bootfs,这是所有容器和宿主机共用的,另一部分是 rootfs,这是每个容器个性化定制的部分。
Docker 的架构中有三个非常核心的概念。第一个是镜像,镜像是只读的模板文件,类似于操作系统的 ISO 文件或者 yum 仓库里的 rpm 包。第二个是容器,容器是基于镜像运行起来的一种持续状态,专业术语叫做容器运行时。第三个是镜像仓库,它是专门用来存放镜像模板的地方,功能和 yum 仓库非常相似。
Docker 的整体架构由四个部分组成。第一部分是 Docker CLI,也就是我们平时使用的命令行工具或者 Web 界面。第二部分是 Docker 守护进程,它负责接收命令并管理容器和镜像。第三部分是容器运行空间,真正运行业务服务的地方。第四部分是镜像仓库,用来存储和分发镜像。
Docker 的工作流程其实很简单。首先通过 docker pull 命令从镜像仓库下载镜像,然后通过 docker run 命令基于镜像创建并启动容器,容器启动后就进入了运行状态,可以随时停止、删除或重新创建。
接下来是 Docker 常用的镜像管理命令。docker images 用来查看本地的镜像列表。docker pull 后面跟上镜像名和标签,可以从仓库拉取镜像。docker rmi 可以根据镜像 ID 或者镜像名加标签来删除镜像。如果这个镜像已经被用来创建了容器,就需要先删除容器,或者在命令后面加上 -f 参数强制删除。docker save 可以把镜像导出成一个文件,方便离线传输。docker load 可以把导出的文件再恢复成镜像。docker inspect 可以查看镜像的详细信息,包括环境变量、入口命令、层信息等。
再来看容器的常用管理命令。docker ps 只能看到正在运行的容器,docker ps -a 可以看到所有状态的容器。docker run 用来创建并运行容器,其中 -i 表示打开标准输入,-t 表示分配一个伪终端,-d 表示让容器在后台以守护进程方式运行,--name 用来指定容器的名字。在 docker run 的最后,还可以指定容器启动后要执行的命令,比如 /bin/bash -c top,这种方式会覆盖镜像中默认的 CMD 配置。
进入容器通常使用 docker exec,它就像远程登录一样,退出容器不会影响容器的运行状态。还有一个命令是 docker attach,也可以进入容器,但退出时会直接导致容器停止。docker exec 还可以在不进入容器的情况下直接执行命令,比如查看目录内容。docker cp 可以在宿主机和容器之间互相拷贝文件,既可以把容器里的文件复制到宿主机,也可以把宿主机的文件复制到容器里。docker rm 用来删除容器,如果容器正在运行,需要加上 -f 参数强制删除。docker inspect 同样适用于容器,可以查看容器的 IP 地址、挂载信息、环境变量等详细数据。
总结一下,Docker 容器技术通过共享宿主机内核、使用镜像模板和容器运行时的方式,实现了应用的标准化封装和快速交付。它非常适合需要频繁更新、大规模部署和高一致性要求的业务场景,比如我们前面提到的一百台服务器每周三更新 Java 版本的例子。通过 Docker,原本繁琐的人工操作可以被简化成一条命令,这就是容器技术真正的价值所在。