【docker系列2】docker 的前世今生
Docker 入门,共 3 篇,将带大家进入 Docker 的世界。
首先了解 Docker 的发展历程,
然后快速掌握 Docker 的基本使用;
Docker 版本及内核兼容性选择是这部分的重点内容。大家如果在生产环境中需要使用 Docker 的话,建议重点关注这一篇。
下面我们就进入第一篇的内容。
Docker 在大多数人眼中几乎是容器(container)的代名词,即使是现在我也常会听到有人说“我在服务器上启动了 N 个 docker 在跑 XX 服务” 之类的话。
我们来看看为何 Docker 能成为容器的代名词,引领容器的时代。
容器技术的发展
chroot
在我看来,要梳理容器技术的发展,最早可以追溯到 1979 年,那时候 chroot 系统调用首次问世。
之后 1982 年 chroot 机制被移植到了 BSD 系统上,再后来便是我们所熟知的 Linux 系统上的 chroot 了。
我们有时会使用 chroot 改变某进程的根目录,使它不能访问该目录之外的其他目录。
这和我们在一个容器内的感觉很像了。事实上在几年前确实有人用一百多行的 bash 利用 chroot 写了一个模拟 Docker 创建容器的实现,称之为 bocker , 有兴趣的读者可以去看看该项目的代码。
这里我们来介绍一个实际使用 chroot 创建隔离环境的例子:
比方说我们想创建一个 Debian 的隔离环境,那可以使用 chroot 将 Debian 的 rootfs 根文件系统作为新进程的根。
至于 rootfs 如何获得,我们这里用 Docker 来完成,但这不是本节的重点,可以暂时忽略它,在以后的章节中我们会详细介绍。
# 创建一个空文件夹
(MoeLove) ➜ ~ mkdir chroot-dir
(MoeLove) ➜ ~ cd chroot-dir
# 使用 Docker 来提取 Debian 的 rootfs
(MoeLove) ➜ chroot-dir docker save -o debian.tar debian:buster
(MoeLove) ➜ chroot-dir ls
debian.tar
(MoeLove) ➜ chroot-dir tar -xf debian.tar
(MoeLove) ➜ chroot-dir ls
098963abf3c3b87b8114ff67d164097dfac2d5659e39f9beb5604db91585f375.json debian.tar repositories
0f28619fe69181d3af529d56692f1362b7a7c8a6bf8dc9ab0d6d4f9ef9b0004d manifest.json
(MoeLove) ➜ chroot-dir mkdir -p debian
(MoeLove) ➜ chroot-dir tar -C debian -xf 0f28619fe69181d3af529d56692f1362b7a7c8a6bf8dc9ab0d6d4f9ef9b0004d/layer.tar
(MoeLove) ➜ chroot-dir ls debian
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
经过上述步骤,就拿到了 Debian 的 rootfs,接下来看看 chroot 的能力:
# 使用 debian 文件夹作为容器的根
(MoeLove) ➜ chroot-dir sudo chroot debian /bin/bash -i
[sudo] tao 的密码:
root@localhost:/# whoami
root
root@localhost:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
此时我们就已经在一个“容器”内了,来看下使用这个“容器”能做些什么。
首先看看当前“容器”内的路由表:
root@localhost:/# mkdir -p /sys
root@localhost:/# mount -t sysfs sys /sys
root@localhost:/# ip r
default via 192.168.0.1 dev wlp2s0 proto dhcp metric 600
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown
192.168.0.0/24 dev wlp2s0 proto kernel scope link src 192.168.0.108 metric 600
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1 linkdown
另外,还可以将 /proc 也挂载进去:
root@localhost:/# mkdir -p /proc
root@localhost:/# mount -t proc proc /proc
# 这里是随意找了一个进程进行查看
root@localhost:/# ls -al /proc/31730/ns/pid
lrwxrwxrwx. 1 1000 1000 0 Jul 29 16:47 /proc/31730/ns/pid -> 'pid:[4026531836]'
可以看到在这个“容器”内,可以访问到主机上的进程信息,这表示没有任何的进程隔离,带来的危险是我们甚至可以在这个“容器”内杀掉主机上的进程,或者通过“容器”来攻击主机。
为了能更好的解决这个问题,接下来出现了另一个技术:Namespace。
Namespace
Namespace 是在 2002 年由 Linux 2.4.19 开始加入内核的特性,它的主要作用是做了一层抽象和隔离,使得在 namespace 中的进程 / 进程组可以看起来拥有自己的独立资源,具体的“资源”表现形式取决于给它赋予了哪些 namespace。
随着 2013 年 Linux 3.8 中 user namespace 的引入,对于我们现在所熟知的容器所需的全部 namespace 就都实现了:mnt、pid、net、ipc、uts、user 和 cgroup 对于这些 Namespace 和 Docker 的关系,我们在以后的章节中都会深入学习,这里先对 Namespace 做下介绍,便于大家了解容器技术的发展。
我们可以通过三个系统调用直接操作 Namespace,这三个系统调用分别是:
- clone,可以通过传递不同 namespace 的标志来为新的(子)进程指定其所属的 namespace;
- unshare,允许一个进程(或线程)取消当前与其他进程(或线程)共享的执行上下文;
- setns,进入文件描述符指定的 namespace。
知道了这些基础知识后,我们回到前面“容器”的内容中。
我们在前面 chroot 的例子中看到没能做到进程隔离,现在来试试看用 namespace 完成该需求。
(MoeLove) ➜ ~ sudo unshare -fp --mount-proc -n
[sudo] tao 的密码:
[root@localhost]/home/tao# ps -a
PID TTY TIME CMD
1 pts/15 00:00:00 zsh
33 pts/15 00:00:00 ps
这里很明显,我们当前所在进程的 PID 为 1 并且看不到宿主机上的其他进程,达到了基础的隔离效果。
cgroups 和 LXC
另一条关键的时间线在 2008 年,cgroups 进入 Linux 2.6.24 后,基于它并且瞄准容器世界的一个项目诞生了。
Linux Container (LXC)结合了 namespace 和 cgroups 等技术,目标就是要创造出运行在 Linux 系统中,并且隔离性良好的容器环境。
LXC 的发布在 2008 年,但值得注意的是 cgroups 最初是由 Google 的工程师开发的,最早的记录是在 2006 年,事实上当时 Google 确实也在做类似的容器化项目。
Docker 的发展
时间一晃而过,就到了 2013 年的 PyCon 上,在这次大会上 Docker 正式面世。而它当时其实也只是构建在 LXC 之上的一个工具,屏蔽掉了 LXC 的使用细节,让用户可以一句 docker run 命令行便创建出自己的容器环境。
同时,它允许用户将容器环境打包成为一个 Docker 镜像进行分发,这也大大降低了用户使用的门槛。 Docker 镜像分发可以说是 Docker 成功的一个关键要素了。
另一个关键要素,我认为是开源生态,Docker 在首次亮相之后不久,就完全开源了,吸引了来自世界各地开发者的关注和积极贡献。
2014 年 Docker 发布 1.0 正式进入生产就绪的状态。在此之前它也将 LXC 逐步从它的底层移除,换成了自己实现的 libcontainer。
此后 Docker 便成为了风靡技术界的新热潮。
再后来也出现过 Swarm Mesos 和 Kubernetes 等众多容器编排系统争夺市场份额的情况,但是随着时间的推移,Kubernetes 成为了事实上的标准,国内外各个公司也都在推进 Kubernetes 的落地和实施。而 Docker 作为容器运行时,也正是极其关键的一环。
总结
从最先的 chroot 到后来的 namespace 和 cgroups 等,再到后来的 LXC 和 Docker 等技术的出现,这都是在容器技术领域的一种探索和前进。

当然,我这里只列出了我认为最核心和关键的内容,事实上当时技术圈除了这条主干之外,也有着很多支线剧情,比如从各类 PaaS (Platform as a Service)厂商的竞争到全面拥抱 Docker ,这些内容也从侧面来反映出了 Docker 的火热。
【docker系列2】docker 的前世今生的更多相关文章
- Docker系列03—Docker 基础入门
本文收录在容器技术学习系列文章总目录 1.概念介绍 1.1 容器 1.1.1 介绍 容纳其它物品的工具,可以部分或完全封闭,被用于容纳.储存.运输物品.物体可以被放置在容器中,而容器则可以保护内容物. ...
- Docker系列05—Docker 存储卷详解
本文收录在容器技术学习系列文章总目录 1.存储卷介绍 1.1 背景 (1)docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加面成,启动容器时,docker会加载只读镜像层并在镜 ...
- Docker系列之Docker镜像(读书笔记)
一.基本概念 Docker包括三个基本概念镜像.容器.仓库. Docker镜像:就是一个只读的模板.例如:一个镜像可以包含一个完整的ubuntu操作系统环境,里面仅安装了Apache或其他应用程序.用 ...
- docker 系列之 docker安装
Docker支持以下的CentOS版本 CentOS 7 (64-bit) CentOS 6.5 (64-bit) 或更高的版本 前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. ...
- Docker系列二: docker常用命令总结
https://docs.docker.com/reference/ 官方命令总结地址 容器生命周期管理 1.docker run 创建一个新的容器并运行一个命令 docker run [optio ...
- Docker系列一: docker简介及基本环境安装
Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从Apache2.0协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然后发布到任何流行的 Li ...
- Docker系列03—Docker 存储卷
一.存储卷介绍 1.1 背景 Docker 的 AFUS 分层文件系统 docker镜像由多个只读层叠加而成,启动容器时,docker会加载只读镜像层并在镜像栈顶部加一个读写层: 如果运行的容器修改了 ...
- Docker系列01—Docker 基础入门
一.初识Docker和容器 1.1 什么是docker 容纳其他物品的工具,可以部分或完全封闭,被用于容纳.存储.运输物品.物体可以被放置在容器中,而容器则可以保护内容物. 容器? 容器就是在隔离的环 ...
- Docker系列04—Docker的网络模式详解
本文收录在容器技术学习系列文章总目录 1.Docker的四种网络模式 (1)docker四种网络模式如下: Bridge contauner 桥接式网络模式 Host(open) containe ...
- Docker系列09—Docker的系统资源限制及验证
本文收录在容器技术学习系列文章总目录 1.限制容器的资源 默认情况下,容器没有资源限制,可以使用主机内核调度程序允许的尽可能多的给定资源.Docker提供了控制容器可以使用多少内存或CPU的方法,设置 ...
随机推荐
- JavaScript 循环判断练习题
JavaScript 循环判断练习题 小明有一组水果("苹果","梨子","香蕉","葡萄","西瓜" ...
- 基于3D NAND层差异的固态盘请求调度算法研究立项 报告
Abstract SSD(Solid State Drive),因其超高的读写性能,以及价格的走低趋势逐渐占据市场,为人们带来更好的用户体验,也为企业级的高并行业务需要提供了一定支持,近几年来SSD的 ...
- MySQL 入门(4):锁
摘要 在这篇文章中,我将从上一篇的一个小例子开始,跟你介绍一下InnoDB中的行锁. 在这里,会涉及到一个概念:两阶段加锁协议. 之后,我会介绍行锁中的S锁和X锁,以及这两种锁的作用. 但是我们会发现 ...
- 设计模式之GOF23中介者模式
中介者模式Mediator 场景:公司中各个部门需要交互,通过中介总经理进行交互 核心: 如果一个系统中对象之间的联系成网状结构,对象之间多对多,将导致关系极其复杂,这些对象统称为“同事关系” 我们可 ...
- C# LinQ的基本子句、协变与异变
//1.from 子句: , , , , , , , , , }; var query = from n in arr select n; foreach (var i in query) { Con ...
- 在没有RedirectAttributes的环境中如何在重定向环境中报错错误提示信息供页面使用
Spring在无RedirectAttributes的情况下(如Interceptor.filter中)使用Flash scope 今天遇到一个应用场景: 在需要在自定义的Interceptor中判断 ...
- 初识spring boot maven管理--HelloWorld
配置文件配置好 了之后可以进行第一个例子的编写了! @Controller @EnableAutoConfiguration() public class SampleController { pri ...
- 字符串匹配算法:Sunday算法
背景 我们第一次接触字符串匹配,想到的肯定是直接用2个循环来遍历,这样代码虽然简单,但时间复杂度却是\(Ω(m*n)\),也就是达到了字符串匹配效率的下限.于是后来人经过研究,构造出了著名的KMP算法 ...
- 8、HTTPS证书Actions无法导出问题
前言 在点Actions时候出现Export Failed:The root certificate could not be located.最近有很多小伙伴在fiddler导出证书的时候,遇到无法 ...
- HttpRequestUtils post get请求
package com.nextjoy.projects.usercenter.util.http; /** * Created by Administrator on 2016/10/20. */ ...