docker是一款非常好用windows系统应用程序。docker为用户建立了一个便于使用的测试环境,以及运输和运行dockerized,利用win系统自带的虚拟化让用户可以基于win进行应用开发,是用户最可靠的开发写编环境。
docker特色说明:
1、合码头平台和工具包括Docker命令行,码头工人和码头工人组成,公证的命令行。
2、便于安装的Windows PC完整的泊坞窗开发环境的设置。
3、每月的边缘和泊坞窗季度稳定版本频道自动更新。
4、够在Linux和Windows服务器环境之间切换来构建应用程序。
5、速和可靠的性能与本机的Windows超V虚拟化。
6、积的代码和数据的安装,包括文件更改通知和方便地访问在本地网络上运行的容器。
7、置业务流程、安全和声明应用程序服务。
8、业网络支持允许Windows操作与VPN Docker。
9、集装箱发展和支持IDE调试。
更多相关介绍
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
Docker简介
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器或Windows机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。
一个完整的Docker有以下几个部分组成:
DockerClient客户端
DockerDaemon守护进程
DockerImage镜像
DockerContainer容器
Docker是PaaS提供商dotCloud开源的一个基于LXC的高级容器引擎,源代码托管在Github上,基于go语言并遵从Apache2.0协议开源。
Docker自2013年以来非常火热,无论是从github上的代码活跃度,还是Redhat在RHEL6.5中集成对Docker的支持,就连Google的ComputeEngine也支持docker在其之上运行。
一款开源软件能否在商业上成功,很大程度上依赖三件事-成功的usercase(用例),活跃的社区和一个好故事。dotCloud之家的PaaS产品建立在docker之上,长期维护且有大量的用户,社区也十分活跃,接下来我们看看docker的故事。
环境管理复杂-从各种OS到各种中间件到各种app,一款产品能够成功作为开发者需要关心的东西太多,且难于管理,这个问题几乎在所有现代IT相关行业都需要面对。
云计算时代的到来-AWS的成功,引导开发者将应用转移到cloud上,解决了硬件管理的问题,然而中间件相关的问题依然存在(所以openstackHEAT和AWScloudformation都着力解决这个问题)。开发者思路变化提供了可能性。
虚拟化手段的变化-cloud时代采用标配硬件来降低成本,采用虚拟化手段来满足用户按需使用的需求以及保证可用性和隔离性。然而无论是KVM还是Xen在docker看来,都在浪费资源,因为用户需要的是高效运行环境而非OS,GuestOS既浪费资源又难于管理,更加轻量级的LXC更加灵活和快速
LXC的移动性-LXC在linux2.6的kernel里就已经存在了,但是其设计之初并非为云计算考虑的,缺少标准化的描述手段和容器的可迁移性,决定其构建出的环境难于迁移和标准化管理(相对于KVM之类image和snapshot的概念)。docker就在这个问题上做出实质性的革新。这是docker最独特的地方。
面对上述几个问题,docker设想是交付运行环境如同海运,OS如同一个货轮,每一个在OS基础上的软件都如同一个集装箱,用户可以通过标准化手段自由组装运行环境,同时集装箱的内容可以由用户自定义,也可以由专业人员制造。这样,交付一个软件,就是一系列标准化组件的集合的交付,如同乐高积木,用户只需要选择合适的积木组合,并且在最顶端署上自己的名字(最后一个标准化组件是用户的app)。这也就是基于docker的PaaS产品的原型。
Docker使用客户端-服务器(C/S)架构模式,使用远程API来管理和创建Docker容器。Docker容器通过Docker镜像来创建。容器与镜像的关系类似于面向对象编程中的对象与类。
Docker采用C/S架构Dockerdaemon作为服务端接受来自客户的请求,并处理这些请求(创建、运行、分发容器)。客户端和服务端既可以运行在一个机器上,也可通过socket或者RESTfulAPI来进行通信。
Dockerdaemon一般在宿主主机后台运行,等待接收来自客户端的消息。Docker客户端则为用户提供一系列可执行命令,用户用这些命令实现跟Dockerdaemon交互。
在docker的网站上提到了docker的典型场景:
Automatingthepackaginganddeploymentofapplications(使应用的打包与部署自动化)
Creationoflightweight,privatePAASenvironments(创建轻量、私密的PAAS环境)
Automatedtestingandcontinuousintegration/deployment(实现自动化测试和持续的集成/部署)
Deployingandscalingwebapps,databasesandbackendservices(部署与扩展webapp、数据库和后台服务)
由于其基于LXC的轻量级虚拟化的特点,docker相比KVM之类最明显的特点就是启动快,资源占用小。因此对于构建隔离的标准化的运行环境,轻量级的PaaS(如dokku),构建自动化测试和持续集成环境,以及一切可以横向扩展的应用(尤其是需要快速启停来应对峰谷的web应用)。
构建标准化的运行环境,现有的方案大多是在一个baseOS上运行一套puppet/chef,或者一个image文件,其缺点是前者需要baseOS许多前提条件,后者几乎不可以修改(因为copyonwrite的文件格式在运行时rootfs是readonly的)。并且后者文件体积大,环境管理和版本控制本身也是一个问题。
PaaS环境是不言而喻的,其设计之初和dotcloud的案例都是将其作为PaaS产品的环境基础
因为其标准化构建方法(buildfile)和良好的RESTAPI,自动化测试和持续集成/部署能够很好的集成进来
因为LXC轻量级的特点,其启动快,而且docker能够只加载每个container变化的部分,这样资源占用小,能够在单机环境下与KVM之类的虚拟化方案相比能够更加快速和占用更少资源
Docker并不是全能的,设计之初也不是KVM之类虚拟化手段的替代品,简单总结几点:
Docker是基于Linux64bit的,无法在32bit的linux/Windows/unix环境下使用
LXC是基于cgroup等linuxkernel功能的,因此container的guest系统只能是linuxbase的
隔离性相比KVM之类的虚拟化方案还是有些欠缺,所有container公用一部分的运行库
网络管理相对简单,主要是基于namespace隔离
cgroup的cpu和cpuset提供的cpu功能相比KVM的等虚拟化方案相比难以度量(所以dotcloud主要是按内存收费)
Docker对disk的管理比较有限
container随着用户进程的停止而销毁,container中的log等用户数据不便收集
针对1-2,有windowsbase应用的需求的基本可以pass了;3-5主要是看用户的需求,到底是需要一个container还是一个VM,同时也决定了docker作为IaaS不太可行。
针对6,7虽然是docker本身不支持的功能,但是可以通过其他手段解决(diskquota,mount--bind)。总之,选用container还是vm,就是在隔离性和资源复用性上做权衡。
另外即便docker0.7能够支持非AUFS的文件系统,但是由于其功能还不稳定,商业应用或许会存在问题,而AUFS的稳定版需要kernel3.8,所以如果想复制dotcloud的成功案例,可能需要考虑升级kernel或者换用ubuntu的server版本(后者提供deb更新)。这也是为什么开源界更倾向于支持ubuntu的原因(kernel版本)
Docker并非适合所有应用场景,Docker只能虚拟基于Linux的服务。WindowsAzure服务能够运行Docker实例,但到目前为止Windows服务还不能被虚拟化。
可能最大的障碍在于管理实例之间的交互。由于所有应用组件被拆分到不同的容器中,所有的服务器需要以一致的方式彼此通信。这意味着任何人如果选择复杂的基础设施,那么必须掌握应用编程接口管理以及集群工具,比如Swarm、Mesos或者Kubernets以确保机器按照预期运转并支持故障切换。
Docker在本质上是一个附加系统。使用文件系统的不同层构建一个应用是有可能的。每个组件被添加到之前已经创建的组件之上,可以比作为一个文件系统更明智。分层架构带来另一方面的效率提升,当你重建存在变化的Docker镜像时,不需要重建整个Docker镜像,只需要重建变化的部分。
可能更为重要的是,Docker旨在用于弹性计算。每个Docker实例的运营生命周期有限,实例数量根据需求增减。在一个管理适度的系统中,这些实例生而平等,不再需要时便各自消亡了。
针对Docker环境存在的不足,意味着在开始部署Docker前需要考虑如下几个问题。首先,Docker实例是无状态的。这意味着它们不应该承载任何交易数据,所有数据应该保存在数据库服务器中。
其次,开发Docker实例并不像创建一台虚拟机、添加应用然后克隆那样简单。为成功创建并使用Docker基础设施,管理员需要对系统管理的各个方面有一个全面的理解,包括Linux管理、编排及配置工具比如Puppet、Chef以及Salt。这些工具生来就基于命令行以及脚本。
Docker核心解决的问题是利用LXC来实现类似VM的功能,从而利用更加节省的硬件资源提供给用户更多的计算资源。同VM的方式不同,LXC其并不是一套硬件虚拟化方法-无法归属到全虚拟化、部分虚拟化和半虚拟化中的任意一个,而是一个操作系统级虚拟化方法,理解起来可能并不像VM那样直观。所以我们从虚拟化到docker要解决的问题出发,看看他是怎么满足用户虚拟化需求的。
用户需要考虑虚拟化方法,尤其是硬件虚拟化方法,需要借助其解决的主要是以下4个问题:
隔离性-每个用户实例之间相互隔离,互不影响。硬件虚拟化方法给出的方法是VM,LXC给出的方法是container,更细一点是kernelnamespace
可配额/可度量-每个用户实例可以按需提供其计算资源,所使用的资源可以被计量。硬件虚拟化方法因为虚拟了CPU,memory可以方便实现,LXC则主要是利用cgroups来控制资源
移动性-用户的实例可以很方便地复制、移动和重建。硬件虚拟化方法提供snapshot和image来实现,docker(主要)利用AUFS实现
安全性-这个话题比较大,这里强调是host主机的角度尽量保护container。硬件虚拟化的方法因为虚拟化的水平比较高,用户进程都是在KVM等虚拟机容器中翻译运行的,然而对于LXC,用户的进程是lxc-start进程的子进程,只是在Kernel的namespace中隔离的,因此需要一些kernel的patch来保证用户的运行环境不会受到来自host主机的恶意入侵,dotcloud(主要是)利用kernelgrsecpatch解决的.
LXC所实现的隔离性主要是来自kernel的namespace,其中pid,net,ipc,mnt,uts等namespace将container的进程,网络,消息,文件系统和hostname隔离开。
pidnamespace
之前提到用户的进程是lxc-start进程的子进程,不同用户的进程就是通过pidnamespace隔离开的,且不同namespace中可以有相同PID。具有以下特征:
每个namespace中的pid是有自己的pid=1的进程(类似/sbin/init进程)
每个namespace中的进程只能影响自己的同一个namespace或子namespace中的进程
因为/proc包含正在运行的进程,因此在container中的pseudo-filesystem的/proc目录只能看到自己namespace中的进程
因为namespace允许嵌套,父namespace可以影响子namespace的进程,所以子namespace的进程可以在父namespace中看到,但是具有不同的pid
正是因为以上的特征,所有的LXC进程在docker中的父进程为docker进程,每个lxc进程具有不同的namespace。同时由于允许嵌套,因此可以很方便的实现LXCinLXC
netnamespace
有了pidnamespace,每个namespace中的pid能够相互隔离,但是网络端口还是共享host的端口。网络隔离是通过netnamespace实现的,
每个netnamespace有独立的networkdevices,IPaddresses,IProutingtables,/proc/net目录。这样每个container的网络就能隔离开来。
LXC在此基础上有5种网络类型,docker默认采用veth的方式将container中的虚拟网卡同host上的一个dockerbridge连接在一起。
ipcnamespace
container中进程交互还是采用linux常见的进程间交互方法(interprocesscommunication-IPC),包括常见的信号量、消息队列和共享内存。然而同VM不同,container的进程间交互实际上还是host上具有相同pidnamespace中的进程间交互,因此需要在IPC资源申请时加入namespace信息-每个IPC资源有一个的32bitID。
mntnamespace
类似chroot,将一个进程放到一个特定的目录执行。mntnamespace允许不同namespace的进程看到的文件结构不同,这样每个namespace中的进程所看到的文件目录就被隔离开了。同chroot不同,每个namespace中的container在/proc/mounts的信息只包含所在namespace的mountpoint。
utsnamespace
UTS(“UNIXTime-sharingSystem”)namespace允许每个container拥有独立的hostname和domainname,使其在网络上可以被视作一个独立的节点而非Host上的一个进程。
usernamespace
每个container可以有不同的user和groupid,也就是说可以以container内部的用户在container内部执行程序而非Host上的用户。
有了以上6种namespace从进程、网络、IPC、文件系统、UTS和用户角度的隔离,一个container就可以对外展现出一个独立计算机的能力,并且不同container从OS层面实现了隔离。然而不同namespace之间资源还是相互竞争的,仍然需要类似ulimit来管理每个container所能使用的资源-LXC采用的是cgroup。
cgroups实现了对资源的配额和度量。cgroups的使用非常简单,提供类似文件的接口,在/cgroup目录下新建一个文件夹即可新建一个group,在此文件夹中新建task文件,并将pid写入该文件,即可实现对该进程的资源控制。具体的资源配置选项可以在该文件夹中新建子subsystem,{子系统前缀}.{资源项}是典型的配置方法,
如memory.usage_in_bytes就定义了该group在subsystemmemory中的一个内存限制选项。
另外,cgroups中的subsystem可以随意组合,一个subsystem可以在不同的group中,也可以一个group包含多个subsystem-也就是说一个subsystem。
关于术语定义
A*cgroup*associatesasetoftaskswithasetofparametersforoneormoresubsystems.A*subsystem*isamodulethatmakesuseofthetaskgroupingfacilitiesprovidedbycgroupstotreatgroupsoftasksinparticularways.Asubsystemistypicallya"resourcecontroller"thatschedulesaresourceorappliesper-cgrouplimits,butitmaybeanythingthatwantstoactonagroupofprocesses,e.g.avirtualizationsubsystem.
我们主要关心cgroups可以限制哪些资源,即有哪些subsystem是我们关心。
cpu:在cgroup中,并不能像硬件虚拟化方案一样能够定义CPU能力,但是能够定义CPU轮转的优先级,因此具有较高CPU优先级的进程会更可能得到CPU运算。通过将参数写入cpu.shares,即可定义改cgroup的CPU优先级-这里是一个相对权重,而非绝对值。当然在cpu这个subsystem中还有其他可配置项,手册中有详细说明。
cpusets:cpusets定义了有几个CPU可以被这个group使用,或者哪几个CPU可以供这个group使用。在某些场景下,单CPU绑定可以防止多核间缓存切换,从而提高效率
memory:内存相关的限制
blkio:blockIO相关的统计和限制,byte/operation统计和限制(IOPS等),读写速度限制等,但是这里主要统计的都是同步IO
net_cls,cpuacct,devices,freezer等其他可管理项。
借助于namespace的隔离机制和cgroup限额功能,LXC提供了一套统一的API和工具来建立和管理container,LXC利用了如下kernel的features:
Kernelnamespaces(ipc,uts,mount,pid,networkanduser)
ApparmorandSELinuxprofiles
Seccomppolicies
Chroots(usingpivot_root)
Kernelcapabilities
Controlgroups(cgroups)
LXC向用户屏蔽了以上kernel接口的细节,提供了如下的组件大大简化了用户的开发和使用工作:
Theliblxclibrary
Severallanguagebindings(python3,luaandGo)
Asetofstandardtoolstocontrolthecontainers
Containertemplates
LXC旨在提供一个共享kernel的OS级虚拟化方法,在执行时不用重复加载Kernel,且container的kernel与host共享,因此可以大大加快container的启动过程,并显著减少内存消耗。在实际测试中,基于LXC的虚拟化方法的IO和CPU性能几乎接近baremetal的性能,大多数数据有相比Xen具有优势。当然对于KVM这种也是通过Kernel进行隔离的方式,性能优势或许不是那么明显,主要还是内存消耗和启动时间上的差异。在参考文献中提到了利用iozone进行DiskIO吞吐量测试KVM反而比LXC要快,而且笔者在devicemappingdriver下重现同样case的实验中也确实能得到如此结论。参考文献从网络虚拟化中虚拟路由的场景(网络IO和CPU角度)比较了KVM和LXC,得到结论是KVM在性能和隔离性的平衡上比LXC更优秀-KVM在吞吐量上略差于LXC,但CPU的隔离可管理项比LXC更明确。
关于CPU,DiskIO,networkIO和memory在KVM和LXC中的比较还是需要更多的实验才能得出可信服的结论。
Docker对container的使用基本是建立在LXC基础之上的,然而LXC存在的问题是难以移动-难以通过标准化的模板制作、重建、复制和移动container。
在以VM为基础的虚拟化手段中,有image和snapshot可以用于VM的复制、重建以及移动的功能。想要通过container来实现快速的大规模部署和更新,这些功能不可或缺。
Docker正是利用AUFS来实现对container的快速更新-在docker0.7中引入了storagedriver,支持AUFS,VFS,devicemapper,也为BTRFS以及ZFS引入提供了可能。但除了AUFS都未经过dotcloud的线上使用,因此我们还是从AUFS的角度介绍。
AUFS(AnotherUnionFS)是一种UnionFS,简单来说就是支持将不同目录挂载到同一个虚拟文件系统下(uniteseveraldirectoriesintoasinglevirtualfilesystem)的文件系统,更进一步地,AUFS支持为每一个成员目录(AKAbranch)设定'readonly','readwrite'和'whiteout-able'权限,同时AUFS里有一个类似
分层的概念,对readonly权限的branch可以逻辑上进行修改(增量地,不影响readonly部分的)。通常UnionFS有两个用途,一方面可以实现不借助LVM,RAID将多个disk和挂在到一个目录下,另一个更常用的就是将一个readonly的branch和一个writeable的branch联合在一起,LiveCD正是基于此可以允许在OSimage不变的基础上允许用户在其上进行一些写操作。Docker在AUFS上构建的containerimage也正是如此,接下来我们从启动container中的linux为例介绍docker在AUFS特性的运用。
典型的Linux启动到运行需要两个FS-bootfs+rootfs(从功能角度而非文件系统角度)(图1)
bootfs(bootfilesystem)主要包含bootloader和kernel,bootloader主要是引导加载kernel,当boot成功后kernel被加载到内存中后bootfs就被umount了.
rootfs(rootfilesystem)包含的就是典型Linux系统中的/dev,/proc,/bin,/etc等标准目录和文件。
由此可见对于不同的linux发行版,bootfs基本是一致的,rootfs会有差别,因此不同的发行版可以公用bootfs如下(图2):
典型的Linux在启动后,首先将rootfs置为readonly,进行一系列检查,然后将其切换为“readwrite”供用户使用。在docker中,起初也是将rootfs以readonly方式加载并检查,然而接下来利用unionmount的将一个readwrite文件系统挂载在readonly的rootfs之上,并且允许再次将下层的filesystem设定为readonly并且向上叠加,这样一组readonly和一个writeable的结构构成一个container的运行目录,每一个被称作一个Layer。如下(图3):
得益于AUFS的特性,每一个对readonly层文件/目录的修改都只会存在于上层的writeable层中。这样由于不存在竞争,多个container可以共享readonly的layer。
所以docker将readonly的层称作“image”-对于container而言整个rootfs都是read-write的,但事实上所有的修改都写入最上层的writeable层中,
image不保存用户状态,可以用于模板、重建和复制。
(图4、5)
上层的image依赖下层的image,因此docker中把下层的image称作父image,没有父image的image称作baseimage(图6)
因此想要从一个image启动一个container,docker会先加载其父image直到baseimage,用户的进程运行在writeable的layer中。所有parentimage中的数据信息以及ID、网络和lxc管理的资源限制等具体container的配置,构成一个docker概念上的container。如下(图7):
由此可见,采用AUFS作为docker的container的文件系统,能够提供如下好处:
1.节省存储空间-多个container可以共享baseimage存储
2.快速部署-如果要部署多个container,baseimage可以避免多次拷贝
3.内存更省-因为多个container共享baseimage,以及OS的disk缓存机制,多个container中的进程命中缓存内容的几率大大增加
4.升级更方便-相比于copy-on-write类型的FS,base-image也是可以挂载为可writeable的,可以通过更新baseimage而一次性更新其之上的container
5.允许在不更改base-image的同时修改其目录中的文件-所有写操作都发生在最上层的writeable层中,这样可以大大增加baseimage能共享的文件内容。
以上5条1-3条可以通过copy-on-write的FS实现,4可以利用其他的unionmount方式实现,5只有AUFS实现的很好。这也是为什么Docker一开始就建立在AUFS之上。
由于AUFS并不会进入linux主干(AccordingtoChristophHellwig,linuxrejectsallunion-typefilesystemsbutUnionMount.),同时要求kernel版本3.0以上(docker推荐3.8及以上),因此在RedHat工程师的帮助下在docker0.7版本中实现了driver机制,AUFS只是其中的一个driver,在RHEL中采用的则是DeviceMapper的方式实现的container文件系统。
grsec是linuxkernel安全相关的patch,用于保护host防止非法入侵。由于其并不是docker的一部分,我们只进行简单的介绍。
grsec可以主要从4个方面保护进程不被非法入侵:
随机地址空间-进程的堆区地址是随机的
用只读的memorymanagementunit来管理进程流程,堆区和栈区内存只包含数据结构/函数/返回地址和数据,是non-executeable
审计和Log可疑活动
编译期的防护
安全永远是相对的,这些方法只是告诉我们可以从这些角度考虑container类型的安全问题可以关注的方面。
牛铺软件园提供《docker》v1.0 官方版下载,该软件为官方版,文件大小为106.MB,推荐指数4颗星,作为学习工具中的顶尖厂商,完全可以放心下载哦!
软件评论
评论列表