Docker
Docker简介与安装
Container技术:
传统的虚拟化技术: 通过对硬件层模拟,从而实现了能够在一套硬件上面运行多个操作系统,因为通过硬件虚拟化,使得操作系统认为在它之下就是硬件层
但是实际情况是这样的:虚拟机中的OS对硬件发出的请求都交给了虚拟的硬件,OS认为指令已经下达了,只要等待硬件返回信息即可,其实OS下面的那层“硬件”是要将指令发送给真正的硬件层来执行的
系统级别的虚拟化技术: 不同于传统的硬件虚拟化,它不需要模拟硬件层 多个虚拟机之间共享Host OS的Kernel内核,所以这些虚拟机是不可以像传统虚拟化技术那种装各种各样的OS,但是它同样可以让跑在里面的应用认为它就是处在一个独立的OS之中,每个虚拟机就像一个容器,里面可以装各种各样的应用,而不同容器中的应用总是认为他们是在一个独立在OS环境下的,所以又称为Container技术
两种虚拟化技术各有优劣,对比如下图:
下面是一张Container技术的结构图:
从图中可以看出,绿蓝红三种颜色的层组合起来就是一台Host主机,在Kernel层之上通过Container技术的三个要点:隔离(namespace),限制(cgroup),记录(chroot) 来虚拟出一个个容器,并管理他们
隔离: 通过namespace机制来避免一些系统级的冲突。 因为每个容器都可以当做一个独立的OS,那么他们就拥有自己的pid进程号等信息,如果这些东西和Host中的相冲突怎么办?毕竟容器不是自己在虚拟化的环境中独立安装一个OS,而是依赖于Host的OS 这时候就可以通过namespace来避免这些冲突,每个容器拥有自己的namespace来管理各自的系统信息
限制: 在Host看来,每个Container都只是一个普通的进程(当时在Container中的应用看来,这些Container都是一个OS),那么怎么来限制这些进程的CPU使用,时间片等资源呢? cgroup是linux内核提供的限制,记录和隔离进程组所用的资源
记录: 上面说过,每个Container都可以当做一个独立的OS,既然它是一个OS那么肯定有自己的文件系统,那么问题又来了,每个Container都有自己的FS,Host也有自己的FS,这么多独立的FS要怎么管理? chroot隔离根文件系统,怎么个说法呢?例如Host的根目录下有a,b目录,并且分别被两个Container当做其根目录。在Host角度来看,ab只是根目录下的两个普通文件夹而已,而对于Container a来说/a就是其根目录;对于Container b来说/b就是其根目录
Docker:
什么是Docker? Docker是一种Container技术的实现,上面说到的Container技术也同样可以用来描述Docker
想一想,我们在开发一个应用的时候 我们在自己的PC上完成了开发工作,并将项目交给测试人员进行测试,但是万一测试的PC上的环境和开发的环境不一样,可能会出现各种各样的问题,同理应用发布到服务器上也是一样的 应用每到一台新的PC中时就要求该PC要装上它需要的所有东西,还要注意版本是不是一致的
而Docker可以帮我们解决这些问题
Docker可以创建一个个Container,前面说过,每个Container都可以当做一个独立的OS,那么我们就可以在这个Container之中进行应用的开发。开发完成之后,我们可以将这个Container打包成一个Image(Image和Container的管理可以理解成:类和实例),可以将其看做是一个集装箱,里面装着应用和应用的各种环境 在测试的PC上,通过Docker将这个集装箱(Image)拿过来通过其创建一个Container就可以直接进行使用和测试,这个Container和开发时使用的Container的环境是一致的(通过一个类实例化出来的各个对象)
Docker翻译为搬运工,它所做的事情也是搬运工一样的
我们可以将应用的各个组件,环境等都装进一个集装箱中,通过Docker运送到各个“码头上”
总结出一个Docker的最最简单的介绍:方便打包发布应用到容器中
我们来看看Docker的层次图:
最底层的lxc,aufs都收kernel内核中运行的
lxc:Linux Container,是Linux上的一种实现Container虚拟化的技术,早期的Docker就基于lxc实现的,最新的版本中已经用libcontainer代替了 aufs:Advanced multi layer Unification FileSystem,翻译成中文就是高级的,分层的,联合的文件系统,它最总要的内容就是可以将两个目录合并在一起,并可以设置操作权限(read-only/read-write)。Docker使用aufs来实现分层的文件管理
倒数第二层的Debian和BusyBox都是在Kernel之上的Image,Image就是一个镜像,可以通过这个镜像来创建多个Container,Image在aufs中是只读的
中间层就是通过Image创建出来的Container,Container在aufs中是可读可写的,通过一个只读的Image创建出一个Container,可以对这个Container进行修改(如上图中添加了一个emacs),然后在打包成一个不可读的Image,而这个Image又可以创建出基于它的Container
通过上面的描述不难得出一个结论:Docker中的Image是层层关联的,每个Image都有一个Parent Image(只有一个除外,那就是Base Image,即最基本的镜像,其他的Image都是在Base Image基础上得到的),使用一个Image时,Docker会找到其Parent Image直到Base Image
Docker在启动Container的时候, aufs会将下层的文件系统设置成read-only,然后将Container的read-write挂载到下层的文件系统之上,构成一个完整的文件系统
在Container中所做的修改不会影响到其所属的Image(因为它是只读的,通过COW技术将要修改的文件复制到read-write层并改写),如果没有保存这个Container(将其打包成一个新的Image),那么当这个Container生命周期结束之后,所做的修改都会消失
这种机制的好处就是,每个阶段的Image都可以进行大量的重用,在创建Container的时候只需要加入不同的部分即可,而不用每次都将全部所需加载一遍
Docker Hub:
类似于Github的服务,用来分发Images,里面有大量的Image提供Docker用户下载,基于这些Image,可以快速的搭建出我们自己所需要的Image 同时我们也可以将自做的Image push到Docker Hub中提供别人下载
Docker安装:
由于是基于Kernel内核的,所以Docker只能跑在Linux上,而且是必须是64位的 在windows和mac系统上的Docker的宿主机并不是windows或者mac,而是借助一个linux虚拟机作为其宿主机
在这里使用VM创建的一个Ubuntu来作为宿主机,在Ubuntu中安装很简单 步骤如下:
sudo apt-get update sudo apt-get install linux-image-generic-lts-raring linux-headers-generic-lts-raring sudo reboot sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9 sudo sh -c "echo deb https://get.docker.io/ubuntu docker main\ > /etc/apt/sources.list.d/docker.list" sudo apt-get update sudo apt-get install lxc-docker
期间可能因为网络的原因会卡很久,完成之后输入
docker
1
如果可以识别命令就是安装成功了
另外,执行docker命令需要root权限,所以除了使用root用户之外,每条命令都要加上sudo 或者也可以通过将当前的用户加入docker用户组(Docker提供的)就可以随时执行docker命令
sudo gpasswd -a ${USER} docker sudo service docker restart #如果没有效果执行下列命令 newgrp - docker #切换当前会话到新 group 因为 groups 命令获取到的是缓存的组信息,刚添加的组信息未能生效,所以 docker images 执行时同样有错。
Docker意义
作者:李遥
Docker在我看来没有多少意义。操作系统进程本身就是虚拟机,而且进程本身就有隔离性。额外再用容器隔离和管理应用是应用设计不良的典型特征(缺乏隔离性、可移植性、可管理性等)编辑于 2017-01-096?收起评论?分享?收藏?感谢?16 条评论切换为时间排序王文武10 个月前没错,SOA即可解决的事情
陈甫鸼10 个月前进程可以隔离,部署没法隔离啊(即便是 .NET
李遥 (作者) 回复陈甫鸼10 个月前部署无法隔离当然是设计不良
陈甫鸼回复李遥 (作者) 10 个月前道理当然可以这么说,但是现实是许多软件在这方面做的就是欠考虑,而功能上又确实必须使用。你说 docker 没有意义,但它确实提供了方法,让人们可以用这样的软件。对那些使用软件的人,怎么能说没有意义呢?2
李遥 (作者) 回复陈甫鸼10 个月前绝大多数需要使用Docker的客户都是要跑服务端的业务系统,这些系统和所使用的底层软件都是有源代码的UNIX软件,都可以用prefix隔离安装1
无名10 个月前docker最核心的实际上是image,规模一上来你就知道docker image有多牛逼3
陈甫鸼回复李遥 (作者) 10 个月前你确定是绝大部份?你确定安装是部署的全部?你确定没有像jupyter 那样表面支持分离但实际上需要全局注册的 bug?还是说,你的工作环境里,你有权要求所有有此类 bug 的软件都不予使用?
李遥 (作者) 回复陈甫鸼10 个月前确实,我承认我说的绝对了。不过很多人用Docker并不是为了克服你说的全局注册的bug,而是懒得/不会指定prefix隔离。这种情况其实是用错误的方式来运维系统,是不应该被鼓励的。从开发哲学上来说,大量使用container技术这也破坏了KISS原则(引入功能重复的间接层)
陈甫鸼回复李遥 (作者) 10 个月前不谈哲学。你的问题不是绝对,而是不理解用 Docker 的项目来源有多复杂。我看到的很多情况是很多UI 服务都在使用 Docker,Jupyter 和 Zeppelin 都有,还有一把的可视化项目。许多情况下运维们不得不上 Docker,经常就是为了对付这些设计上的问题,否则就得浪费宝贵的 VM 资源。都是穷出来的办法,我们也承认本可以简单,但要求运维自己去 fix 所有相关软件的 bug,实在是要求太高了。2
李遥 (作者) 回复陈甫鸼10 个月前某种程度上说,这是UNIX项目历史上就不强调部署隔离的恶果,现在有了docker来walk around,以后恐怕这个趋势更不能逆转了。恐怕运维得一直陷入在Get Shit Running的困境里另一方面,一个high profile项目如果不尊重部署隔离的话,本身就反映了设计水平,其前景其实是堪忧的 ...
毛海鉴10 个月前嗯,集装箱没有任何意义,打包容积利用率上不去那是工人水平问题,这额外的一层铁皮明显违背了kiss嘛赞
毛海鉴10 个月前抽象有什么意义?面向对象有什么意义?抽象概念在c里面就可以很好表达,增加抽象降低效率明显违背了kiss。 c有什么意义?可读性有什么意义?写不了汇编机器码那是程序员水平问题,增加一个编译器明显违背了kiss。1
陈甫鸼回复李遥 (作者) 10 个月前问题是谁能保证每一个设计都这么深思熟虑之后才上马?重视部署规范化也就是最近几年的事情,在那之前,Get shit done 才是常态,也不只是 UNIX 的问题。现在有了Docker,至少我们可以 get shit done,才能谈论改进。Linux 毕竟还有 Docker,某些公司现在还陷在里头出不来呢。
Gavin Lin10 个月前设计能贯彻kiss的是点,胶水代码覆盖的是面,大多数时候人们都在写胶水代码,什么时候kiss能把写代码的过程变成点,kiss才有更大的讨论空间吧赞
李宏杰8 个月前确实像进程,可是你怎么移植