视频笔记:Docker 特性及其相关工具 - Tom Verelst

https://www.youtube.com/watch?v=heBI7oQvHZUhtml

http://v.qq.com/page/o/8/j/o03134mlm8j.html前端

基本介绍

Docker 很像(但不是)一个轻量级的虚拟机,有本身的shell, namespace, network interface,能够以root运行东西,有本身的服务和软件包node

虚拟机有虚拟硬件层和一个运行其上的完整系统。而容器则是直接将进程运行于现有内核上。因此启动Docker很是轻量级,启动很是快速。linux

Docker组成部分,简单来看,分为三个角色,客户端、docker 主机、docker registry。
客户端运行 docker run, build, pull等命令;
docker host 则有一个docker daemon 在运行,它维护着本地的container和image;
docker registry则是集中管理全部image的地方,docker host将从docker registry取得image。git

Docker 文件系统是分层的,这是基于Union FS的概念,在Ubuntu上使用的是aufs,能够很天然的支持这种概念。而在CentOS/RHEL上则只能使用DeviceMapper去模拟,性能和稳定性以及一些功能会有问题。在 Linux 3.18 之后,可使用 Overlay FS,这也是 Union FS 的实现。docker

Docker 文件系统分层,最底层是 bootfs(kernel),而后是镜像中的各类层,最后是运行期的容器的层。容器的存储层在容器中止后,即被废弃。shell

严格来讲并非在容器中止后就被销毁。容器中止后,其存储层依然附属于中止掉的容器。若是利用 docker start 将容器启动后,会发现其内文件系统的变更依然存在。而这种容器存储层被废弃的概念则是指另外一个层面的事情。json

容器应当被视为 immutable 的,所以容器内部的变更应该能够随时被抛弃,不但愿丢失的变化部分应该存储于挂载的数据卷中。后端

因此docker的工做流是 docker run, stop, rm, 再次run。每一次run都是从image创建的新鲜的container,因此里面的内容永远是image的状态,而没有上一次container中的修改。因此从这个工做流程理解,container中的变更被废弃了。缓存

Docker 1.10 发布更新了Layer的ID问题,曾经使用的是随机UUID,可是发生过冲突,并且很难判断相同UUID的layer究竟是哪一个。因此从1.10开始,将其升级为密码学 Hash 值,SHA256。这样能够确保其内容统一,并且Image将会更小。在 1.10 之前,Image 和 Layer 基本是一个完整的东西,可是 1.10 以后,因为使用了 SHA256,Image 和 Layer 能够分开复用重复的Layer,这样Image能够更小。因为这种变化,若是从 1.10 之前的版本过来,必需要升级全部 images。

Docker 容器文件层会在中止后被废弃,那么数据应该存储于挂载的卷中。而挂载卷能够是数据卷也能够是本地文件,注意是“本地”,不可使用NFS, SMB之类的位置进行挂载,这样Docker会认为其不安全。若是须要相似的云存储,可使用volume的driver,能够支持AWS S3之类的存储。

docker run 一个容器,容器能够定义 EXPOSE 某些端口,而这些端口是容器之间能够访问的,而不是从外部访问,若是须要这些端口暴露于外部,那么应该用 -p 或 --publish,将该端口发布于宿主,能够映射不一样端口。

Dockerfile, docker build, images, run

Dockerfile 是分步骤的,而每一步都会被缓存,因此从新构建很是快。

ENTRYPOINTCMD 不一样,通常 ENTRYPOINT 是要运行的命令,而 CMD 则是参数,docker run 后面所跟随的其实是 CMD,也就是参数。有些镜像把 ENTRYPOINT 设为了 sh -c,这样 CMD 能够跟 bash 命令和脚本,因此一些人误觉得 CMD 就是命令。其实它们只是做为参数送给了 ENTRYPOINT 中指定的 sh -c

基本命令:build, run, stop, start, ps, ps -a, images, rmi
将镜像push到registry,docker login, docker push

Docker 历史

Docker 的历史是和 Linux 内核发布历史紧密相关的。

2007年 Linux 发布内核 2.6.24

有个特性被添加进来,Control Groups(cgroups)。随后,使用 cgroups 的 Linux Containers (lxc) 发布。cgroups 是今天 Docker 的基础。

cgroups ,能够限制资源使用,设置优先级,会计,控制。

距演讲者说,Linux 中的 nice,实际上就是使用 cgroups 中优先级的功能。
https://en.wikipedia.org/wiki/Nice_(Unix)
不过应该不是。

控制的部分包括freezerestart

(这部分的内容演讲者讲的有些错误,我查询了一下,进行修正。

2013年2月 Linux 发布了内核 3.8

http://kernelnewbies.org/Linux_3.8#head-fc2604c967c200a26f336942caee2440a2a4099c

此次完整的实现了 namespace 的隔离,包括了 pid, network, hostname, mount pic, user 的namespace。

正是此次发布构成了Docker的基础,同年3月份 Docker 项目正式成为开源项目。最开始基于 lxc,如今抽象出来了 libcontainer,统一接口,下面能够支持多种容器组合,默认使用的是 runC,不过能够换。

2014年8月 Linux 发布了内核 3.16

cgroups 进行了从新设计。 http://lwn.net/Articles/601840/

Docker Networking 中的 overlay network 所依赖的就是此次内核的改进。

2014年12月 Linux发布了内核 3.18

通过多年的努力,此次终于第一次在内核中加入了 Union FS的实现,此次是 Overlay fs。(Ubuntu中的aufs争取了好多年,最后做者懒得争取了,放弃了)。这样对于红帽系未来的服务器,也就终于有可能有Union FS可用了。之前只能凑合用 Device Mapper,并且本地loop仍是不适合在生产环境使用的。因此要使用 overlay 存储层,须要内核在 3.18 以上。

2015年4月 Linux发布了内核 4.0

docker 1.12 中的 overlay2 存储层就依赖的是此次的内核对 overlay 驱动的改进。

2016年 Linux 发布了内核 4.5

更加完全的改造了 cgroups,称为 cgroups2,而且承认其已经稳定。
http://kernelnewbies.org/Linux_4.5#head-621383bcd8bc104aed825c9ebc08a0b986690f8a

使用 Docker 的好处

很是容易扩展,因为全部东西都打包在一个容器里了,因此部署的时候不须要在服务器上进行安装了,因此很适合扩展。

Docker 容器是 immutable 的,能够将其视为乐高积木,若是哪一个坏了,扔了换个新的,而不是在旧的上面修修补补。

DevOps,开发人员(Dev)只须要考虑容器内的东西便可,而运营人员(Ops)则只需负责容器外部便可。

持续集成(Continuous Integration)

确保全部环境彻底同样,不会出现“个人机器上没问题啊”这种状况。运行、测试都在容器内。

编排(Orchestration)工具

Compose, Machine, Swarm, Networking

Compose

定义运行多容器应用,单机没问题,多主机还在试验中。

实例中,值得注意的是,他的目录结构。docker-compose.yml 在项目根目录,每一个应用都有本身独立目录,以及其目录下存在 Dockerfile。这种感受更干净。(或许在LNMP示例项目中,我不该该把conf都存在于同一个目录下,而是应该分应用创建目录,对应的配置放在各自目录下。)

另外须要注意的是,在仅有几台的应用环境下,他依然定义了前端网络和后端网络,让两个网络独立。

在启动示例的过程当中,Tom Vereist 提到了这个例子写的很差的一点,在 worker 项目中,它在容器里使用 maven 对项目进行了构建。这不是一个好的写法,这会致使maven的安装,编译开发工具的安装、依赖的安装等等,会产生一个很是大的镜像。建议的作法是能够在另外一个容器中构建,把构建后的软件包拿到运行的容器中安装使用便可,避免运行时不须要的东西存在于容器中。

Machine

用于建立、管理 docker host,能够支持多种云平台,提供统一的访问接口。

Swarm

docker 集群工具,多宿主管理运行。

能够定义 docker host 的 label。经过 docker daemon 的 --label 设置;经过 docker-machine --engine-label, --label 设置;将 docker host 设置上标签。而后在运行的时候能够经过约束标签,来决定该容器运行于那些 docker host 上。

能够定义过滤器,包括两大类,节点(Node)或容器(Container)。节点多是约束、健康程度等;容器能够是端口、依赖等。

Networking

建立 Overlay network。替代 link (bridge),link 在一些动态环境下使用会有问题。好比一群容器启动后,link的某一个节点挂了,从新运行,使用了新的ip,而还在运行的docker使用的仍是旧的ip去联系该节点,致使没法链接。因此只可以把全部节点都down掉,而后从新运行。

尝试了一下,两个没有link关系的容器,能够经过容器IP访问对方。因此 link 是创建一种识别的办法,而不是安全上的创建通道的概念。看了一下文档,提到了 --icc=false 的参数来建立网络隔离。
https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks

link (bridge)使用两种方式传递给宿主其link的主机位置,环境变量和/etc/hosts文件。
https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/#communication-across-links

而多宿主环境中,使用 docker network 建立 overlay network,使用link连接主机,则会有一个内置的DNS进行名字的动态维护,再也不使用 /etc/hosts

在Tom 演示 docker swarm 的时候,我发现他和我同样创建了一个 bash 脚原本启动创建 docker host。我以为应该考虑作个工具使用 yaml 描述文件来创建 docker-machine,就像 docker-compose作的那样。命令行中有太多的重复信息了。

脚本最后是使用 docker network 建立 overlay 网络,Tom 提到一点,须要指定 --subnet ,不然将没法连通,特别是跨主机的时候,有的版本有bug,同一个网络不必定使用同一段IP地址。不过如今这个bug已经修复了,不指定地址跨主机没问题。

演示 swarm 的过程当中碰到了和我碰到的同样的问题。在单机环境中,在 docker compose 中可使用 build 来构建镜像。可是在 swarm 的多宿主环境中,这样作的结果会致使全部的 service 会扔到同一个 docker host 中去,而若是打算使用多宿主环境(也是为何要用swarm 的初衷),则必须使用 registry 中的 image。这样宿主能够主动去 registry 下载 image。可使用 docker hub 的服务,或者本身架设 registry。

而且不可使用 link 了,而必须使用 自定义network。Tom 说这是因为一个 link 的bug,如今不知道是否已经解决了,须要试验。

经过 environment:"constraint:type==frontend" 的形式来指定约束。

Tom 不推荐在生产环境中使用 compose + swarm,由于碰到了太多的问题,他甚至本身还报告了一个bug #2866。

其它工具

Docker Cloud (cloud.docker.com)

建立 node clusters,能够选择AWS, Digital Ocean, Azure,Softlayer等几大云服务商。而后可使用docker hub上的镜像进行部署。创建 Stack 须要脚本,很像compose,其实他们应该支持compose脚本更合适,创建service。

Docker Cloud 适合小规模云的部署。

Kubernetes

由 Google 开发,用 Go 语言写的。Google 每周用这个运行2百万个containers。

一个 kubernetes 集群由 master 和 minions 组成。master 含有 etcd、scheduler;而每一个 minon 含有 kubelet,proxy 和一群 pod。

CoreOS

不须要安装 docker,它包含了 linux container。它也使用 etcd,所不一样的是它每个 host都运行etcd,这样避免了单点故障。fleetd,很像是网络多宿主环境下的 systemd,它负责开启中止分布在宿主中的服务。

Lattice

Flocker

Docker Security

Container Security

container 自己很安全,因为 isolation,只使用必要的依赖。
可使用 --security-opt sec comp:xxx.json,来指定安全策略。
Unikernel,能够很是灵活定制的内核,只选择所必须的组件使用,其它的都抛弃,信任域更小。

Node Security

如今 docker daemon 必须以 root 运行。如今的受权机制是 all or nothing,或者能够管理全部 docker,或者彻底没有权限管理。这点未来可能会改变。

相关文章
相关标签/搜索