2013年2月,前Gluster的CEO Ben Golub和dotCloud的CEO Solomon Hykes坐在一块儿聊天时,Solomon谈到想把dotCloud内部使用的Container容器技术单独拿出来开源,而后围绕这个技术开一家新公司提供技术支持。28岁的Solomon在使用python开发dotCloud的PaaS云时发现,使用 LXC(Linux Container) 技术能够打破产品发布过程当中应用开发工程师和系统工程师二者之间没法轻松协做发布产品的难题。这个Container容器技术能够把开发者从平常部署应用的繁杂工做中解脱出来,让开发者能专心写好程序;从系统工程师的角度来看也是同样,他们迫切须要从各类混乱的部署文档中解脱出来,让系统工程师专一在应用的水平扩展、稳定发布的解决方案上。他们越深刻交谈,越以为这是一次云技术的变革,紧接着在2013年3月Docker 0.1发布,拉开了基于云计算平台发布产品方式的变革序幕。html
Docker 是 Docker.Inc 公司开源的一个基于 LXC技术之上构建的Container容器引擎, 源代码托管在 GitHub 上, 基于Go语言并听从Apache2.0协议开源。 Docker在2014年6月召开DockerConf 2014技术大会吸引了IBM、Google、RedHat等业界知名公司的关注和技术支持,不管是从 GitHub 上的代码活跃度,仍是Redhat宣布在RHEL7中正式支持Docker, 都给业界一个信号,这是一项创新型的技术解决方案。 就连 Google 公司的 Compute Engine 也支持 docker 在其之上运行, 国内“BAT”先锋企业百度Baidu App Engine(BAE)平台也是以Docker做为其PaaS云基础。python
Docker产生的目的就是为了解决如下问题:linux
1) 环境管理复杂: 从各类OS到各类中间件再到各类App,一款产品可以成功发布,做为开发者须要关心的东西太多,且难于管理,这个问题在软件行业中广泛存在并须要直接面对。Docker能够简化部署多种应用实例工做,好比Web应用、后台应用、数据库应用、大数据应用好比Hadoop集群、消息队列等等均可以打包成一个Image部署。如图所示:git
2) 云计算时代的到来: AWS的成功, 引导开发者将应用转移到云上, 解决了硬件管理的问题,然而软件配置和管理相关的问题依然存在 (AWS cloudformation是这个方向的业界标准, 样例模板可参考这里)。Docker的出现正好能帮助软件开发者开阔思路,尝试新的软件管理方法来解决这个问题。github
3) 虚拟化手段的变化: 云时代采用标配硬件来下降成本,采用虚拟化手段来知足用户按需分配的资源需求以及保证可用性和隔离性。然而不管是KVM仍是Xen,在 Docker 看来都在浪费资源,由于用户须要的是高效运行环境而非OS, GuestOS既浪费资源又难于管理, 更加轻量级的LXC更加灵活和快速。如图所示:docker
4) LXC的便携性: LXC在 Linux 2.6 的 Kernel 里就已经存在了,可是其设计之初并不是为云计算考虑的,缺乏标准化的描述手段和容器的可便携性,决定其构建出的环境难于分发和标准化管理(相对于KVM之类image和snapshot的概念)。Docker就在这个问题上作出了实质性的创新方法。数据库
以Fedora 20做为主机为例,直接安装docker-io:安全
$ sudo yum -y install docker-io
启动docker后台Daemon:网络
$ sudo systemctl start docker
跑咱们第一个Hello World容器:dom
$ sudo docker run -i -t fedora /bin/echo hello world Hello world
能够看到在运行命令行后的下一行会打印出经典的Hello World字符串。
Docker核心是一个操做系统级虚拟化方法, 理解起来可能并不像VM那样直观。咱们从虚拟化方法的四个方面:隔离性、可配额/可度量、便携性、安全性来详细介绍Docker的技术细节。
每一个用户实例之间相互隔离, 互不影响。 通常的硬件虚拟化方法给出的方法是VM,而LXC给出的方法是container,更细一点讲就是kernel namespace。其中pid、net、ipc、mnt、uts、user等namespace将container的进程、网络、消息、文件系统、UTS("UNIX Time-sharing System")和用户空间隔离开。
1) pid namespace
不一样用户的进程就是经过pid namespace隔离开的,且不一样 namespace 中能够有相同pid。全部的LXC进程在docker中的父进程为docker进程,每一个lxc进程具备不一样的namespace。同时因为容许嵌套,所以能够很方便的实现 Docker in Docker。
2) net namespace
有了 pid namespace, 每一个namespace中的pid可以相互隔离,可是网络端口仍是共享host的端口。网络隔离是经过net namespace实现的, 每一个net namespace有独立的 network devices, IP addresses, IP routing tables, /proc/net 目录。这样每一个container的网络就能隔离开来。docker默认采用veth的方式将container中的虚拟网卡同host上的一个docker bridge: docker0链接在一块儿。
3) ipc namespace
container中进程交互仍是采用linux常见的进程间交互方法(interprocess communication - IPC), 包括常见的信号量、消息队列和共享内存。然而同 VM 不一样的是,container 的进程间交互实际上仍是host上具备相同pid namespace中的进程间交互,所以须要在IPC资源申请时加入namespace信息 - 每一个IPC资源有一个惟一的 32 位 ID。
4) mnt namespace
相似chroot,将一个进程放到一个特定的目录执行。mnt namespace容许不一样namespace的进程看到的文件结构不一样,这样每一个 namespace 中的进程所看到的文件目录就被隔离开了。同chroot不一样,每一个namespace中的container在/proc/mounts的信息只包含所在namespace的mount point。
5) uts namespace
UTS("UNIX Time-sharing System") namespace容许每一个container拥有独立的hostname和domain name, 使其在网络上能够被视做一个独立的节点而非Host上的一个进程。
6) user namespace
每一个container能够有不一样的 user 和 group id, 也就是说能够在container内部用container内部的用户执行程序而非Host上的用户。
cgroups 实现了对资源的配额和度量。 cgroups 的使用很是简单,提供相似文件的接口,在 /cgroup目录下新建一个文件夹便可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,便可实现对该进程的资源控制。groups能够限制blkio、cpu、cpuacct、cpuset、devices、freezer、memory、net_cls、ns九大子系统的资源,如下是每一个子系统的详细说明:
以上九个子系统之间也存在着必定的关系.详情请参阅官方文档。
AUFS (AnotherUnionFS) 是一种 Union FS, 简单来讲就是支持将不一样目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)的文件系统, 更进一步的理解, AUFS支持为每个成员目录(相似Git Branch)设定readonly、readwrite 和 whiteout-able 权限, 同时 AUFS 里有一个相似分层的概念, 对 readonly 权限的 branch 能够逻辑上进行修改(增量地, 不影响 readonly 部分的)。一般 Union FS 有两个用途, 一方面能够实现不借助 LVM、RAID 将多个disk挂到同一个目录下, 另外一个更经常使用的就是将一个 readonly 的 branch 和一个 writeable 的 branch 联合在一块儿,Live CD正是基于此方法能够容许在 OS image 不变的基础上容许用户在其上进行一些写操做。Docker 在 AUFS 上构建的 container image 也正是如此,接下来咱们从启动 container 中的 linux 为例来介绍 docker 对AUFS特性的运用。
典型的启动Linux运行须要两个FS: bootfs + rootfs:
bootfs (boot file system) 主要包含 bootloader 和 kernel, bootloader主要是引导加载kernel, 当boot成功后 kernel 被加载到内存中后 bootfs就被umount了. rootfs (root file system) 包含的就是典型 Linux 系统中的 /dev, /proc,/bin, /etc 等标准目录和文件。
对于不一样的linux发行版, bootfs基本是一致的, 但rootfs会有差异, 所以不一样的发行版能够公用bootfs 以下图:
典型的Linux在启动后,首先将 rootfs 设置为 readonly, 进行一系列检查, 而后将其切换为 "readwrite" 供用户使用。在Docker中,初始化时也是将 rootfs 以readonly方式加载并检查,然而接下来利用 union mount 的方式将一个 readwrite 文件系统挂载在 readonly 的rootfs之上,而且容许再次将下层的 FS(file system) 设定为readonly 而且向上叠加, 这样一组readonly和一个writeable的结构构成一个container的运行时态, 每个FS被称做一个FS层。以下图:
得益于AUFS的特性, 每个对readonly层文件/目录的修改都只会存在于上层的writeable层中。这样因为不存在竞争, 多个container能够共享readonly的FS层。 因此Docker将readonly的FS层称做 "image" - 对于container而言整个rootfs都是read-write的,但事实上全部的修改都写入最上层的writeable层中, image不保存用户状态,只用于模板、新建和复制使用。
上层的image依赖下层的image,所以Docker中把下层的image称做父image,没有父image的image称做base image。所以想要从一个image启动一个container,Docker会先加载这个image和依赖的父images以及base image,用户的进程运行在writeable的layer中。全部parent image中的数据信息以及 ID、网络和lxc管理的资源限制等具体container的配置,构成一个Docker概念上的container。以下图:
安全永远是相对的,这里有三个方面能够考虑Docker的安全特性:
因为安全属于很是具体的技术,这里不在赘述,请直接参阅Docker官方文档。
咱们再来看看Docker社区还有哪些子项目值得咱们去好好研究和学习。基于这个目的,我把有趣的核心项目给你们罗列出来,让热心的读者能快速跟进本身感兴趣的项目:
Docker社区一直在面对技术挑战,从容地给出本身的解决方案。云计算发展至今,有不少重要的问题没有获得妥善解决,Docker正在尝试让主流厂商接受并应用它。至此,以上Docker技术的预览到此告一段落,笔者也但愿读者能结合本身的实际状况,尝试使用Docker技术。由于只有在亲自体会的基础之上,像Docker这样的云技术才会产生更大的价值。