8 个你可能不知道的 Docker 知识

自从上世纪 90
年代硬件虚拟化被主流的技术广泛普及之后,对数据中心而言,发生的最大的变革莫过于容器和容器管理工具,例如:Docker。在过去的一年
内,Docker 技术已经逐渐走向成熟,并且推动了大型初创公司例如 Twitter 和 Airbnb 的发展,甚至在银行、连锁超市、甚至
NASA 的数据中心都赢得了一席之地。当我几年前第一次直到 Docker 的时候,我还对 Docker 的未来持怀疑的态度,我认为他们是把以前的
Linux 容器的概念拿出来包装了一番推向市场。但是使用 Docker 成功进行了几个项目 例如 Spantree 之后,我改变了我的看法:Docker 帮助我们节省了大量的时间和经历,并且已经成为我们技术团队中不可或缺的工具。

GitHub
上面每天都会催生出各式各样的工具、形态各异的语言和千奇百怪的概念。如果你和我一样,没有时间去把他们全部都测试一遍,甚至没有时间去亲自测试
Docker,那么你可以看一下我的这篇文章:我将会用我们在 Docker 中总结的经验来告诉你什么是 Docker、为什么 Docker
会这么火。

Docker 是容器管理工具

Docker
是一个轻量级、便携式、与外界隔离的容器,也是一个可以在容器中很方便地构建、传输、运行应用的引擎。和传统的虚拟化技术不同的是,Docker
引擎并不虚拟出一台虚拟机,而是直接使用宿主机的内核和硬件,直接在宿主机上运行容器内应用。也正是得益于此,Docker
容器内运行的应用和宿主机上运行的应用性能差距几乎可以忽略不计。

但是 Docker 本身并不是一个容器系统,而是一个基于原有的容器化工具 LXC 用来创建虚拟环境的工具。类似 LXC 的工具已经在生产环境中使用多年,Docker 则基于此提供了更加友好的镜像管理工具和部署工具。

Docker 不是虚拟化引擎

Docker 第一次发布的时候,很多人都拿 Docker 和虚拟机 VMware、KVM 和 VirtualBox
比较。尽管从功能上看,Docker 和虚拟化技术致力于解决的问题都差不多,但是 Docker
却是采取了另一种非常不同的方式。虚拟机是虚拟出一套硬件,虚拟机的系统进行的磁盘操作,其实都是在对虚拟出来的磁盘进行操作。当运行 CPU
密集型的任务时,是虚拟机把虚拟系统里的 CPU
指令“翻译”成宿主机的CPU指令并进行执行。两个磁盘层,两个处理器调度器,两个操作系统消耗的内存,所有虚拟出的这些都会带来相当多的性能损失,一台
虚拟机所消耗的硬件资源和对应的硬件相当,一台主机上跑太多的虚拟机之后就会过载。而 Docker 就没有这种顾虑。Docker
运行应用采取的是“容器”的解决方案:使用 namespace 和 CGroup
进行资源限制,和宿主机共享内核,不虚拟磁盘,所有的容器磁盘操作其实都是对 /var/lib/docker/ 的操作。简言之,Docker 其实只是在宿主机中运行了一个受到限制的应用程序。

从上面不难看出,容器和虚拟机的概念并不相同,容器也并不能取代虚拟机。在容器力所不能及的地方,虚拟机可以大显身手。例如:宿主机是
Linux,只能通过虚拟机运行 Windows,Docker 便无法做到。再例如,宿主机是 Windows,Windows 并不能直接运行
Docker,Windows上的 Docker 其实是运行在 VirtualBox 虚拟机里的。

Docker 使用层级的文件系统

前面提到过,Docker 和现有容器技术 LXC 等相比,优势之一就是 Docker 提供了镜像管理。对于 Docker
而言,镜像是一个静态的、只读的容器文件系统的快照。然而不仅如此,Docker
中所有的磁盘操作都是对特定的Copy-On-Write文件系统进行的。下面通过一个例子解释一下这个问题。

例如我们要建立一个容器运行 JAVA Web 应用,那么我们应该使用一个已经安装了 JAVA 的镜像。在
Dockerfile(一个用于生成镜像的指令文件)中,应该指明“基于 JAVA 镜像”,这样 Docker 就会去 Docker Hub
Registry 上下载提前构建好的 JAVA 镜像。然后再 Dockerfile 中指明下载并解压 Apache Tomcat 软件到 /opt/tomcat 文件夹中。这条命令并不会对原有的 JAVA 镜像产生任何影响,而仅仅是在原有镜像上面添加了一个改动层。当一个容器启动时,容器内的所有改动层都会启动,容器会从第一层中运行 /usr/bin/java 命令,并且调用另外一层中的 /opt/tomcat/bin
命令。实际上,Dockerfile 中每一条指令都会产生一个新的改动层,即便只有一个文件被改动。如果用过 Git
就能更清楚地认识这一点,每条指令就像是每次 commit,都会留下记录。但是对于 Docker
来说,这种文件系统提供了更大的灵活性,也可以更方便地管理应用程序。

我们Spantree的团队有一个自己维护的含有 Tomcat 的镜像。发布新版本也非常简单:使用 Dockerfile
将新版本拷贝进镜像从而创建一个新镜像,然后给新镜像贴上版本的标签。不同版本的镜像的不同之处仅仅是一个 90 MB 大小的 WAR
文件,他们所基于的主镜像都是相同的。如果使用虚拟机去维护这些不同的版本的话,还要消耗掉很多不同的磁盘去存储相同的系统,而使用 Docker
就只需要很小的磁盘空间。即便我们同时运行这个镜像的很多实例,我们也只需要一个基础的 JAVA / TOMCAT 镜像。

Docker 可以节约时间

很多年前我在为一个连锁餐厅开发软件时,仅仅是为了描述如何搭建环境都需要写一个 12 页的 Word 文档。例如本地 Oracle
数据库,特定版本的
JAVA,以及其他七七八八的系统工具和共享库、软件包。整个搭建过程浪费掉了我们团队每个人几乎一天的时间,如果用金钱衡量的话,花掉了我们上万美金的
时间成本。虽然客户已经对这种事情习以为常,甚至认为这是引入新成员、让成员适应环境、让自己的员工适应我们的软件所必须的成本,但是相比较起来,我们宁
愿把更多的时间花在为客户构建可以增进业务的功能上面。

如果当时有 Docker,那么构建环境就会像使用自动化搭建工具 Puppet / Chef / Salt / Ansible
一样简单,我们也可以把整个搭建时间周期从一天缩短为几分钟。但是和这些工具不同的地方在于,Docker
可以不仅仅可以搭建整个环境,还可以将整个环境保存成磁盘文件,然后复制到别的地方。需要从源码编译 Node.js 吗?Docker
做得到。Docker 不仅仅可以构建一个 Node.js 环境,还可以将整个环境做成镜像,然后保存到任何地方。当然,由于 Docker
是一个容器,所以不用担心容器内执行的东西会对宿主机产生任何的影响。

现在新加入我们团队的人只需要运行 docker-compose up 命令,便可以喝杯咖啡,然后开始工作了。

Docker 可以节省开销

当然,时间就是金钱。除了时间外,Docker 还可以节省在基础设施硬件上的开销。高德纳和麦肯锡的研究表明,数据中心的利用率在 6% -
12% 左右。不仅如此,如果采用虚拟机的话,你还需要被动地监控和设置每台虚拟机的 CPU 硬盘和内存的使用率,因为采用了静态分区(static
partitioning)所以资源并不能完全被利用。。而容器可以解决这个问题:容器可以在实例之间进行内存和磁盘共享。你可以在同一台主机上运行多个
服务、可以不用去限制容器所消耗的资源、可以去限制资源、可以在不需要的时候停止容器,也不用担心启动已经停止的程序时会带来过多的资源消耗。凌晨三点的
时候只有很少的人会去访问你的网站,同时你需要比较多的资源执行夜间的批处理任务,那么可以很简单的便实现资源的交换。

虚拟机所消耗的内存、硬盘、CPU 都是固定的,一般动态调整都需要重启虚拟机。而用 Docker 的话,你可以进行资源限制,得益于
CGroup,可以很方便动态调整资源限制,让然也可以不进行资源限制。Docker
容器内的应用对宿主机而言只是两个隔离的应用程序,并不是两个虚拟机,所以宿主机也可以自行去分配资源。

Docker 有一个健壮的镜像托管系统

前面提到过,这个托管系统就叫做 Docker Hub Registry。截止到 2015年4月29日,互联网上大约有 14000 个公共的
Docker,而大部分都被托管在 Docker Hub 上面。和 Github 已经很大程度上成为开源项目的代表一样,Docker 官方的
Docker Hub 则已经是公共 Docker 镜像的代表。这些镜像可以作为你应用和数据服务的基础。

也正是得益于此,你可以随意尝试最新的技术:说不定有些人就把图形化数据库的实例打包成了 Docker 镜像托管在上面。再例如
Gitlab,手工搭建 Gitlab 非常困难,译者不建议普通用户去手工搭建,而如果使用 Docker
Gitlab,这个镜像则会五秒内便搭建完成。再例如特定 Ruby 版本的 Rails 应用,再例如 Linux 上的 .NET
应用,这些都可以使用简单的一条 Docker 命令搭建完成。

Docker 官方镜像都有 official 标签,安全性可以保证。但是第三方镜像的安全性无法保证,所以请谨慎下载第三方镜像。生产环境下可以只使用第三方提供的 Dockerfile 构建镜像。

Docker Github 介绍:5 秒内搞定一个 Gitlab

关于 Linux 上的 .NET 应用和 Rails 应用,将会在以后的文章中做详细介绍。

Docker 可以避免产生 Bug

Spantree 一直是“固定基础设置”(immutable
infrastructure)的狂热爱好者。换句话说,除非有心脏出血这种漏洞,我们尽量不对系统做升级,也尽量不去改变系统的设置。当添加新服务器的
时候,我们也会从头构建服务器的系统,然后直接将镜像导入,将服务器放入负载均衡的集群里,然后对要退休的服务器进行健康检查,检查完毕后移除集群。得益
于 Docker 镜像可以很轻松的导入导出,我们可以最大程度地减少因为环境和版本问题导致的不兼容,即便有不兼容了也可以很轻松地回滚。当然,有了
Docker,我们在生产、测试和开发中的运行环境得到统一。以前在协同开发时,会因为每个人开发的电脑配置不同而导致“在我的电脑上是能运行的,你的怎
么不行”的情况,而如今 Docker 已经帮我们解决了这个问题。

Docker 目前只能运行在 Linux 上

前面也提到过,Docker 使用的是经过长时间生产环境检验的技术,虽然这些技术已经都出现很长时间了,但是大部分技术都还是 Linux
独有的,例如 LXC 和 Cgroup。也就是说,截止到现在,Docker 容器内只能在 Linux 上运行 Linux
上的服务和应用。Microsoft 正在和 Docker 紧密合作,并且已经宣布了下一个版本的 Windows Server 将会支持
Docker 容器,并且命名为 Windows Docker,估计采用的技术应该是Hyper-V
Container,我们有望在未来的几年内看到这个版本。

除此之外,类似 boot2docker 和 Docker Machine 这种工具已经可以让我们在 Mac 和 Windows 下通过虚拟机运行 Docker 了。

时间: 2024-09-28 21:24:54

8 个你可能不知道的 Docker 知识的相关文章

你根本不知道的冷知识,看完我惊呆了,原来.....

有些冷知识,非常的有趣,而且说不定就是之后与人交流的谈资,所以,这些必须收藏. 历史文学 1. 朱熹一辈子不吃豆腐 3.方孝儒是中国历史上唯一一个被"株十族"的人 4.猫是<圣经>里唯一没有提到的家养动物 5.埃及金字塔四面均为等边三角形,正对东南西北四个方位 6.条条大路通罗马的原因如图: 科学百科 1. 兔子不会流汗 2.玫瑰和苹果属同科,百合和大葱属同科 3.一张纸不能对折8次 4.北极熊是左撇子 5. dreamt 是唯一以"mt"结尾的英文单词

你可能不知道的 docker 命令的奇淫怪巧

原文:你可能不知道的 docker 命令的奇淫怪巧 你可能不知道的 docker 命令的奇淫怪巧 Intro 介绍并收录一些可能会用到的一些简单实用却很少有人用的 docker 命令 dangling images build 自己的 docker 镜像的时候,有时会遇到用一个甚至多个中间层镜像,这会一定程度上减少最终打包出来 docker 镜像的大小,但是会产生一些tag 为 none 的无用镜像,也称为悬挂镜像 (dangling images) 列出所有的 dangling images:

一些你可能不知道的JavaScript知识(知道了之后可是大大有用的哦)

1.!!将一个值方便快速转化为布尔值 console.log( !!window===true ); 2.不声明第三个变量实现交换 var a=1,b=2; a=[b,b=a][0];//执行完这句代码之后 a的值为2 b的值为1了 3.&&和||的用法 (学会了立马感觉高大尚了吧) 用代码说话吧 var day=(new Date).getDay()===0; //传统if语句 if (day) { alert('Today is Sunday!'); }; //运用逻辑与代替if da

你不能不知道的前端知识体系

一.框架与组件 bootstrap等UI框架设计与实现 伸缩布局:grid网格布局 基础UI样式:元素reset.按钮.图片.菜单.表单 组件UI样式:按钮组.字体图标.下拉菜单.输入框组.导航组.面包屑.分页.标签.轮播.弹出框.列表.多媒体.警告 响应式布局:布局.结构.样式.媒体.javascript响应式 第三方插件:插件管理 jQuery.zepto使用原理以及插件开发 支持amd.cmd.全局变量的模块化封装 $.fn.method = function(){} mvc/mvvm框架

你所不知道的html5与html中的那些事(二)

文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5的父亲html的一些

你所不知道的SQL Server数据库启动过程(用户数据库加载过程的疑难杂症)

前言 本篇主要是上一篇文章的补充篇,上一篇我们介绍了SQL Server服务启动过程所遇到的一些问题和解决方法,可点击查看,我们此篇主要介绍的是SQL Server启动过程中关于用户数据库加载的流程,并且根据加载过程中所遇到的一系列问题提供解决方案. 其实SQL Server作为微软的一款优秀RDBMS,它启动的过程中,本身所带的那些系统库发生问题的情况相对还是很少的,我们在平常使用中,出问题的大部分集中于我们自己建立的用户数据库. 而且,相对于侧重面而言,其实我们更关注的是我们自己建立的用户数

你所不知道的JavaScript数组

你所不知道的JavaScript数组 相信每一个 javascript 学习者,都会去了解 JS 的各种基本数据类型,数组就是数据的组合,这是一个很基本也十分简单的概念,他的内容没多少,学好它也不是件难事情.但是本文着重要介绍的并不是我们往常看到的 Array,而是 ArrayBuffer. 我写的很多东西都是因为要完成某些特定的功能而刻意总结的,可以算是备忘,本文也是如此!前段时间一直在研究 Web Audio API 以及语音通信相关的知识,内容侧重于音频流在 AudioContext 各个

你可能不知道的陷阱, IEnumerable接口

IEnumerable枚举器接口的重要性,说一万句话都不过分.几乎所有集合都实现了这个接口,Linq的核心也依赖于这个万能的接口.C语言的for循环写得心烦,foreach就顺畅了很多. 我很喜欢这个接口,但在使用中也遇到不少的疑问,你是不是也有与我一样的困惑: (1) IEnumerable 与  IEnumerator到底有什么区别 (2) 枚举能否越界访问,越界访问是什么后果?为什么在枚举中不能改变集合的值? (3) Linq的具体实现到底是怎样的,比如Skip,它跳过了一些元素,那么这些

你可能不知道的一些机器学习事儿

                                  你可能不知道的一些机器学习事儿 最近零零碎碎地看了很多机器学习方法的东西,增长了不少新知识.有很多小技巧虽然不会出现在教科书中,但它们真的很实用. (1)随机森林模型不适合用稀疏特征. (2)测试集必须使用与训练集相同的方法进行预处理. (3)L1正则(特征选择)最小样本数目m与特征n呈log关系,m = O(log n) : L2正则(旋转不变)最小样本数目m与特征n呈线性关系,m = O(n) . (4)标准的PCA是一种线