Docker技术入门与实战(第2版).-阿里云开发者社区

开发者社区> 华章出版社> 正文

Docker技术入门与实战(第2版).

简介:

40bf3a469448c860bfa8bc108663beb9c408b5ec


容器技术系列

Docker技术入门与实战

第2版

杨保华 戴王剑 曹亚仑 编著





图书在版编目(CIP)数据

Docker技术入门与实战 / 杨保华,戴王剑,曹亚仑编著. —2版. —北京:机械工业出版社,2017.1

(容器技术系列)

ISBN 978-7-111-55582-7

I. D… II. ①杨… ②戴… ③曹… III. Linux操作系统-程序设计 IV. TP316.85

中国版本图书馆CIP数据核字(2016)第308604号

本书从Docker基本原理开始,深入浅出地讲解Docker的构建与操作,内容系统全面,可帮助开发人员、运维人员快速部署Docker应用。本书分为四大部分:基础入门、实战案例、进阶技能和开源项目。第一部分(第1~8章)介绍Docker与虚拟化技术的基本概念,包括安装、镜像、容器、仓库、数据卷,端口映射等;第二部分(第9~16章)通过案例介绍Docker的应用方法,包括各种操作系统平台、SSH服务的镜像、Web服务器与应用、数据库的应用、各类编程语言的接口、容器云等,还介绍了作者在容器实战中的思考与经验总结;第三部分(第17~21章)介绍一些进阶技能,如Docker核心技术实现原理、安全、高级网络配置、libernetwork插件化网络功能等;第四部分(第22~28章)介绍与容器开发相关的开源项目,包括Etcd、Docker Machine、Docker Compose、Docker Swarm、Mesos和Kubernetes等。

第2版参照Docker技术的最新进展对全书内容进行了修订,并增加了第四部分专门介绍与容器相关的知名开源项目,利用好这些优秀的开源平台,可以更好地在生产实践中受益。











Docker技术入门与实战(第2版)

出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)

责任编辑:吴 怡 责任校对:董纪丽

印  刷:北京市荣盛彩色印刷有限公司 版  次:2017年2月第2版第1次印刷

开  本:186mm×240mm 1/16 印  张:25.5

书  号:ISBN 978-7-111-55582-7 定  价:69.00元

凡购本书,如有缺页、倒页、脱页,由本社发行部调换

客服热线:(010)88379426 88361066 投稿热线:(010)88379604

购书热线:(010)68326294 88379649 68995259 读者信箱:hzit@hzbook.com

版权所有 ? 侵权必究

封底无防伪标均为盗版

本书法律顾问:北京大成律师事务所 韩光/邹晓东






Preface?第2版前言

自云计算步入市场算起,新一代计算技术刚好走过了第一个十年。

在过去十年里,围绕计算、存储、网络三大基础服务,围绕敏捷服务和规模处理两大核心诉求,新的概念、模式和工具争相涌现。这些创新的开源技术成果,提高了整个信息产业的生产效率,降低了应用信息技术的门槛,让“互联网+”成为可能。

如果说软件定义网络(SDN)和网络功能虚拟化(NFV)让互联网络的虚拟化进入了崭新的阶段,那么容器技术的出现,毫无疑问称得上计算虚拟化技术的又一大创新。从Linux Container到Docker,看似是计算技术发展的一小步,却是极为重要的历史性突破。容器带来的不仅仅是技术体验上的改进,更多的是新的开发模式、新的应用场景、新的业务可能……

容器技术自身在快速演进的同时,笔者也很欣喜地看到,围绕着容器的开源生态系统越发繁盛。Docker三剑客Machine、Compose、Swarm相辅相成,集团作战;搜索巨人则推出Kubernetes,领航新一代容器化应用集群平台;还有Mesos、CoreOS,以及其他众多的开源工具。这些工具的出现,弥补了现有容器技术栈的不足,极大地丰富了容器技术的应用场景,增强了容器技术在更多领域的竞争力。

在第2版中,笔者参照容器技术最新进展对全书内容进行了修订完善,并增加了第四部分专门介绍与容器相关的知名开源项目,利用好这些优秀的开源平台,可以更好地在生产实践中受益。

成书之际,Docker发布了1.13版本,带来了更稳定的性能和更多有趣的特性。

再次感谢容器技术,感谢开源文化,希望开源技术能得到更多的支持和贡献!

最后,IBM中国研究院的刘天成、李玉博等帮忙审阅了部分内容,在此表达最深厚的感谢!


杨保华

2016年12月于北京






第1版前言?Preface

在一台服务器上同时运行一百个虚拟机,肯定会被认为是痴人说梦。而在一台服务器上同时运行一千个Docker容器,这已经成为现实。在计算机技术高速发展的今天,昔日的天方夜谭正在一个个变成现实。

多年的研发和运维(DevOps)经历中,笔者时常会碰到这样一个困境:用户的需求越来越多样,系统的规模越来越庞大,运行的软件越来越复杂,环境配置问题所造成的麻烦层出不穷……为了解决这些问题,开源社区推出过不少优秀的工具。这些方案虽然在某些程度上确能解决部分“燃眉之急”,但是始终没有一种方案能带来“一劳永逸”的效果。

让作为企业最核心资源的工程师们花费大量的时间,去解决各种环境和配置引发的 Bug,这真的正常吗?

回顾计算机的发展历程,最初,程序设计人员需要直接操作各种枯燥的机器指令,编程效率之低可想而知。高级语言的诞生,将机器指令的具体实现成功抽象出来,从此揭开了计算机编程效率突飞猛进的大时代。那么,为什么不能把类似的理念(抽象与分层)也引入到现代的研发和运维领域呢?

Docker无疑在这一方向上迈出了具有革新意义的一步。笔者在刚接触Docker时,就为它所能带来的敏捷工作流程而深深吸引,也为它能充分挖掘云计算资源的效能而兴奋不已。我们深信,Docker的出现,必将给DevOps技术,甚至整个信息技术产业的发展带来深远的影响。

笔者曾尝试编写了介绍Docker技术的中文开源文档。短短一个月的时间,竟收到了来自全球各个地区超过20万次的阅读量和全五星的好评。这让我们看到国内技术界对于新兴开源技术的敏锐嗅觉和迫切需求,同时也倍感压力,生怕其中有不妥之处,影响了大家学习和推广Docker技术的热情。在开源文档撰写过程中,我们一直在不断思考,在生产实践中到底怎么用Docker才是合理的?在“华章图书”的帮助下,终于有了现在读者手中的这本书。

与很多技术类书籍不同,本书中避免一上来就讲述冗长的故事,而是试图深入浅出、直奔主题,在最短时间内让读者理解和掌握最关键的技术点,并且配合实际操作案例和精炼的点评,给读者提供真正可以上手的实战指南。

本书在结构上分为三大部分。第一部分是Docker技术的基础知识介绍,这部分将让读者对Docker技术能做什么有个全局的认识;第二部分将具体讲解各种典型场景的应用案例,供读者体会Docker在实际应用中的高效秘诀;第三部分将讨论一些偏技术环节的高级话题,试图让读者理解Docker在设计上的工程美学。最后的附录归纳了应用Docker的常见问题和一些常用的参考资料。读者可根据自身需求选择阅读重点。全书主要由杨保华和戴王剑主笔,曹亚仑写作了编程开发和实践之道章节。

本书在写作过程中参考了官方网站上的部分文档,并得到了DockerPool技术社区网友们的积极反馈和支持,在此一并感谢!

成稿之际,Docker已经发布了增强安全特性的1.3.2版本。衷心祝愿Docker及相关技术能够快速成长和成熟,让众多IT从业人员的工作和生活都更加健康、更加美好!


作者于2014年11月






目  录?Contents

第2版前言

第1版前言

第一部分 基础入门

第1章 初识容器与Docker  3

1.1 什么是Docker  3

1.2 为什么要使用Docker  5

1.3 Docker与虚拟化  7

1.4 本章小结  9

第2章 核心概念与安装配置  10

2.1 核心概念  10

2.2 安装Docker  11

2.2.1 Ubuntu环境下安装Docker  12

2.2.2 CentOS环境下安装Docker  14

2.2.3 通过脚本安装  14

2.2.4 Mac OS环境下安装Docker  15

2.2.5 Windows环境下安装Docker  20

2.3 配置Docker服务  21

2.4 推荐实践环境  22

2.5 本章小结  22

第3章 使用Docker镜像  23

3.1 获取镜像  23

3.2 查看镜像信息  25

3.3 搜寻镜像  28

3.4 删除镜像  29

3.5 创建镜像  31

3.6 存出和载入镜像  32

3.7 上传镜像  33

3.8 本章小结  33

第4章 操作Docker容器  34

4.1 创建容器  34

4.2 终止容器  39

4.3 进入容器  40

4.4 删除容器  42

4.5 导入和导出容器  42

4.6 本章小结  44

第5章 访问Docker仓库  45

5.1 Docker Hub公共镜像市场  45

5.2 时速云镜像市场  47

5.3 搭建本地私有仓库  48

5.4 本章小结  50

第6章 Docker数据管理  51

6.1 数据卷  51

6.2 数据卷容器  52

6.3 利用数据卷容器来迁移数据  53

6.4 本章小结  54

第7章 端口映射与容器互联  55

7.1 端口映射实现访问容器  55

7.2 互联机制实现便捷互访  57

7.3 本章小结  59

第8章 使用Dockerfile创建镜像  60

8.1 基本结构  60

8.2 指令说明  62

8.3 创建镜像  67

8.4 使用.dockerignore文件  67

8.5 最佳实践  67

8.6 本章小结  68

第二部分 实战案例

第9章 操作系统  71

9.1 BusyBox  71

9.2 Alpine  72

9.3 Debian/Ubuntu  74

9.4 CentOS/Fedora  76

9.5 本章小结  77

第10章 为镜像添加SSH服务  78

10.1 基于commit命令创建  78

10.2 使用Dockerfile创建  80

10.3 本章小结  82

第11章 Web服务与应用  83

11.1 Apache  83

11.2 Nginx  87

11.3 Tomcat  88

11.4 Jetty  92

11.5 LAMP  93

11.6 CMS  94

11.6.1 WordPress  94

11.6.2 Ghost  96

11.7 持续开发与管理  96

11.7.1 Jenkins  97

11.7.2 Gitlab  98

11.8 本章小结  99

第12章 数据库应用  100

12.1 MySQL  100

12.2 MongoDB  102

12.2.1 使用官方镜像  102

12.2.2 使用自定义Dockerfile  104

12.3 Redis  106

12.4 Memcached  108

12.5 CouchDB  108

12.6 Cassandra  109

12.7 本章小结  110

第13章 分布式处理与大数据平台  111

13.1 RabbitMQ  111

13.2 Celery  113

13.3 Hadoop  114

13.4 Spark  115

13.4.1 使用官方镜像  116

13.4.2 验证  116

13.5 Storm  117

13.6 Elasticsearch  119

13.7 本章小结  120

第14章 编程开发  121

14.1 C/C++  121

14.1.1 GCC  121

14.1.2 LLVM  122

14.1.3 Clang  122

14.2 Java  123

14.3 Python  124

14.3.1 使用官方的Python镜像  124

14.3.2 使用PyPy  124

14.4 JavaScript  125

14.5 Go  127

14.5.1 搭建并运行Go容器  127

14.5.2 Beego  130

14.5.3 Gogs:基于Go的Git服务  130

14.6 PHP  130

14.7 Ruby  132

14.7.1 使用Ruby官方镜像  132

14.7.2 JRuby  133

14.7.3 Ruby on Rails  134

14.8 Perl  135

14.9 R  136

14.10 Erlang  138

14.11 本章小结  140

第15章 容器与云服务  141

15.1 公有云容器服务  141

15.1.1 AWS  141

15.1.2 Google Cloud Platform  142

15.1.3 Azure  143

15.1.4 腾讯云  144

15.1.5 阿里云  144

15.1.6 华为云  144

15.1.7 UCloud  145

15.2 容器云服务  145

15.2.1 基本要素与关键特性  146

15.2.2 网易蜂巢  146

15.2.3 时速云  147

15.2.4 Daocloud  148

15.2.5 灵雀云  148

15.2.6 数人云  149

15.3 阿里云容器服务  150

15.4 时速云容器平台  151

15.5 本章小结  153

第16章 容器实战思考  154

16.1 Docker为什么会成功  154

16.2 研发人员该如何看容器  155

16.3 容器化开发模式  156

16.4 容器与生产环境  158

16.5 本章小结  160

第三部分 进阶技能

第17章 Docker核心实现技术  163

17.1 基本架构  163

17.2 命名空间  165

17.3 控制组  167

17.4 联合文件系统  169

17.5 Linux网络虚拟化  171

17.6 本章小结  174

第18章 配置私有仓库  175

18.1 安装Docker Registry  175

18.2 配置TLS证书  177

18.3 管理访问权限  178

18.4 配置Registry  181

18.4.1 示例配置  181

18.4.2 选项  183

18.5 批量管理镜像  188

18.6 使用通知系统  190

18.6.1 相关配置  190

18.6.2 Notif?ication的使用场景  192

18.7 本章小结  193

第19章 安全防护与配置  194

19.1 命名空间隔离的安全  194

19.2 控制组资源控制的安全  195

19.3 内核能力机制  195

19.4 Docker服务端的防护  197

19.5 更多安全特性的使用  197

19.6 使用第三方检测工具  198

19.6.1 Docker Bench  198

19.6.2 clair  199

19.7 本章小结  199

第20章 高级网络功能  201

20.1 网络启动与配置参数  201

20.2 配置容器DNS和主机名  203

20.3 容器访问控制  204

20.4 映射容器端口到宿主主机的实现  206

20.5 配置docker0网桥  207

20.6 自定义网桥  208

20.7 使用OpenvSwitch网桥  209

20.8 创建一个点到点连接  211

20.9 本章小结  212

第21章 libnetwork插件化网络功能  213

21.1 容器网络模型  213

21.2 Docker网络相关命令  215

21.3 构建跨主机容器网络  216

21.4 本章小结  219

第四部分 开源项目

第22章 Etcd——高可用的键值数据库  223

22.1 简介  223

22.2 安装和使用Etcd  224

22.3 使用etcdctl客户端  228

22.3.1 数据类操作  230

22.3.2 非数据类操作  233

22.4 Etcd集群管理  236

22.4.1 构建集群  236

22.4.2 集群参数配置  238

22.5 本章小结  240

第23章 Docker三剑客之Docker Machine  241

23.1 简介  241

23.2 安装Machine  241

23.3 使用Machine  243

23.4 Machine命令  244

23.5 本章小结  247

第24章 Docker三剑客之Docker Compose  248

24.1 简介  248

24.2 安装与卸载  249

24.3 Compose命令说明  252

24.4 Compose环境变量  257

24.5 Compose模板文件  257

24.6 Compose应用案例一:Web负载均衡  266

24.7 Compose应用案例二:大数据Spark集群  271

24.8 本章小结  273

第25章 Docker三剑客之Docker Swarm  274

25.1 简介  274

25.2 安装Swarm  275

25.3 使用Swarm  277

25.4 使用其他服务发现后端  281

25.5 Swarm中的调度器  282

25.6 Swarm中的过滤器  284

25.7 本章小结  286

第26章 Mesos——优秀的集群资源调度平台  287

26.1 简介  287

26.2 Mesos安装与使用  288

26.3 原理与架构  296

26.3.1 架构  296

26.3.2 基本单元  297

26.3.3 调度  297

26.3.4 高可用性  298

26.4 Mesos配置项解析  299

26.4.1 通用项  299

26.4.2 master专属项  299

26.4.3 slave专属项  301

26.5 日志与监控  304

26.6 常见应用框架  306

26.7 本章小结  307

第27章 Kubernetes——生产级容器集群平台  308

27.1 简介  308

27.2 核心概念  309

27.2.1 集群组件  311

27.2.2 资源抽象  312

27.2.3 辅助概念  315

27.3 快速体验  318

27.4 安装部署  322

27.5 重要组件  331

27.5.1 Etcd  332

27.5.2 kube-apiserver  332

27.5.3 kube-scheduler  333

27.5.4 kube-controller-manager  333

27.5.5 kubelet  334

27.5.6 kube-proxy  335

27.6 使用kubectl  337

27.6.1 获取kubectl  337

27.6.2 命令格式  337

27.6.3 全局参数  338

27.6.4 子命令  339

27.7 网络设计  351

27.8 本章小结  353

第28章 其他相关项目  354

28.1 平台即服务方案  354

28.1.1 Deis  354

28.1.2 Flynn  355

28.2 持续集成平台Drone  355

28.3 容器管理  357

28.3.1 Citadel  357

28.3.2 Shipyard  358

28.3.3 DockerUI  358

28.3.4 Panamax  358

28.3.5 Seagull  359

28.3.6 Dockerboard  361

28.4 编程开发  362

28.5 网络支持  363

28.5.1 pipework  363

28.5.2 Flannel   364

28.5.3 Weave Net  364

28.5.4 Calico   365

28.6 日志处理  366

28.6.1 Docker-Fluentd  366

28.6.2 Logspout  367

28.6.3 Sematext-agent-docker  368

28.7 服务代理工具  368

28.7.1 Traefik  369

28.7.2 Muguet  370

28.7.3 nginx-proxy  370

28.8 标准与规范  372

28.9 其他项目  375

28.9.1 CoreOS  375

28.9.2 OpenStack支持  375

28.9.3 dockerize  376

28.9.4 Unikernel  378

28.9.5 容器化的虚拟机  378

28.10 本章小结  379

附录

附录A 常见问题总结  382

附录B Docker命令查询  388

附录C 参考资源链接  393

第一部分 Part 1
基?础?入?门
第1章 初识容器与Docker
第2章 核心概念与安装配置
第3章 使用Docker镜像
第4章 操作Docker容器
第5章 访问Docker仓库
第6章 Docker数据管理
第7章 端口映射与容器互联
第8章 使用Dockerf?ile创建镜像

本部分共有8章内容,笔者将介绍Docker和容器的相关基础知识。
第1章介绍Docker的前世与今生,以及它与现有的虚拟化技术,特别是Linux容器技术的关系。
第2章介绍Docker的三大核心概念,以及如何在常见的操作系统环境中安装Docker。
第3章到第5章通过具体的示例,讲解使用Docker的常见操作,包括镜像、容器和仓库。
第6章剖析如何在Docker中使用数据卷来保存持久化数据。
第7章介绍如何使用端口映射和容器互联来方便外部对容器服务的访问。
第8章介绍如何编写Dockerf?ile配置文件,以及使用Dockerf?ile来创建镜像的具体方法和注意事项。

第1章
初识容器与Docker
如果说主机时代大家比拼的是单个服务器物理性能(如CPU主频和内存),那么在云时代,最为看重的则是凭借虚拟化技术所构建的集群处理能力。
伴随着信息技术的飞速发展,虚拟化技术早已经广泛应用到各种关键场景中。从20世纪60年代IBM推出的大型主机虚拟化,到后来以Xen、KVM为代表的虚拟机虚拟化,再到现在以Docker为代表的容器技术,虚拟化技术自身也在不断进行创新和突破。
传统来看,虚拟化既可以通过硬件模拟来实现,也可以通过操作系统软件来实现。而容器技术则更为优雅,它充分利用了操作系统本身已有的机制和特性,可以实现远超传统虚拟机的轻量级虚拟化。因此,有人甚至把它称为“新一代的虚拟化”技术,并将基于容器打造的云平台亲切地称为“容器云”。
Docker毫无疑问正是众多容器技术中的佼佼者,是容器技术发展过程中耀眼的一抹亮色。那么,什么是Docker?它会带来哪些好处?它跟现有虚拟化技术又有何关系?
本章首先会介绍Docker项目的起源和发展过程,之后会为大家剖析Docker和相关容器技术,以及它在DevOps等场景带来的巨大便利。最后,还将阐述Docker在整个虚拟化领域中的技术定位。
1.1 什么是Docker
1.?Docker开源项目背景
Docker是基于Go语言实现的开源容器项目,诞生于2013年年初,最初发起者是dotCloud公司。Docker自开源后受到广泛的关注和讨论,目前已有多个相关项目(包括Docker三剑客、Kubernetes等),逐渐形成了围绕Docker容器的生态体系。
由于Docker在业界造成的影响力实在太大,dotCloud公司后来也直接改名为Docker Inc,并专注于Docker相关技术和产品的开发。

图1-1 Docker官方网站
Docker项目已加入了Linux基金会,并遵循Apache2.0协议,全部开源代码均在https://github.com/docker/docker上进行维护。在Linux基金会最近一次关于“最受欢迎的云计算开源项目”的调查中,Docker仅次于2010年发起的OpenStack项目,并仍处于上升趋势。
现在主流的Linux操作系统都已经支持Docker。例如,红帽公司的RHEL 6.5/CentOS 6.5往上的操作系统、Ubuntu 14.04往上的操作系统,都已经在软件源中默认带有Docker软件包。Google公司宣称在其PaaS(Platform as a Service)平台及服务产品中广泛应用了Docker容器。IBM公司跟Docker公司达成了战略合作伙伴关系。微软公司在其云平台Azure上加强了对Docker的支持。公有云提供商亚马逊也推出了AWS EC2 Container服务,提供对Docker和容器业务的支持。
Docker的构想是要实现“Build, Ship and Run Any App, Anywhere”,即通过对应用的封装(Packaging)、分发(Distribution)、部署(Deployment)、运行(Runtime)生命周期进行管理,达到应用组件“一次封装,到处运行”的目的。这里的应用组件,既可以是一个Web应用、一个编译环境,也可以是一套数据库平台服务,甚至是一个操作系统或集群。
基于Linux平台上的多项开源技术,Docker提供了高效、敏捷和轻量级的容器方案,并支持部署到本地环境和多种主流云平台。可以说,Docker首次为应用的开发、运行和部署提供了“一站式”的实用解决方案。
2.?Linux容器技术——巨人的肩膀
跟大部分新兴技术的诞生一样,Docker也并非“从石头缝里蹦出来的”,而是站在前人的肩膀上,其中最重要的就是Linux容器(Linux Containers,LXC)技术。
IBM DeveloperWorks网站关于容器技术的描述十分准确:“容器有效地将由单个操作系统管理的资源划分到孤立的组中,以更好地在孤立的组之间平衡有冲突的资源使用需求。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心CPU本地运行指令,而不需要任何专门的解释机制。此外,也避免了准虚拟化(paravirtualization)和系统调用替换中的复杂性。”
当然,LXC也经历了长期的演化。最早的容器技术可以追溯到1982年Unix系列操作系统上的chroot工具(直到今天,主流的Unix、Linux操作系统仍然支持和带有该工具)。早期的容器实现技术包括Sun Solaris操作系统上的Solaris Containers(2004年发布),FreeBSD操作系统上的FreeBSD jail(2000年左右出现),以及GNU/Linux上的Linux-VServer和OpenVZ。
在LXC之前,这些相关技术经过多年的演化已经十分成熟和稳定,但是由于种种原因,它们并没有被很好地集成到主流的Linux内核中,用户使用起来并不方便。例如,如果用户要使用OpenVZ技术,需要先手动给操作系统打上特定的内核补丁方可使用,而且不同版本并不一致。类似的困难造成在很长一段时间内,这些优秀的技术只流传于技术人员的小圈子中。
后来LXC项目借鉴了前人成熟的容器设计理念,并基于一系列新引入的内核特性,实现了更具扩展性的虚拟化容器方案。更加关键的是,LXC终于被集成到了主流Linux内核中,进而成为了Linux系统轻量级容器技术的事实标准。从技术层面来看,LXC已经趟过了绝大部分的“坑”,完成了容器技术实用化的大半历程。
3.?从Linux容器到Docker
在LXC的基础上,Docker进一步优化了容器的使用体验,让它进入了寻常百姓家。
首先,Docker提供了各种容器管理工具(如分发、版本、移植等)让用户无需关注底层的操作,可以更简单明了地管理和使用容器;其次,Docker通过引入分层文件系统构建和高效的镜像机制,降低了迁移难度,极大地提升了用户体验。用户操作Docker容器就像操作应用自身一样简单。
早期的Docker代码实现是直接基于LXC的。自0.9版本开始,Docker开发了libcontainer项目,作为更广泛的容器驱动实现,从而替换掉了LXC的实现。目前,Docker还积极推动成立了runC标准项目,试图让容器支持不再局限于Linux操作系统,而是更安全、更具扩展性。
简单地讲,读者可以将Docker容器理解为一种轻量级的沙盒(sandbox)。每个容器内运行着一个应用,不同的容器相互隔离,容器之间也可以通过网络互相通信。容器的创建和停止都十分快速,几乎跟创建和终止原生应用一致;另外,容器自身对系统资源的额外需求也十分有限,远远低于传统虚拟机。很多时候,甚至直接把容器当作应用本身也没有任何问题。
有理由相信,Docker技术会进一步成熟,将成为更受欢迎的容器虚拟化技术实现,并在云计算和DevOps等领域得到更广泛的应用。
1.2 为什么要使用Docker
1.?Docker容器虚拟化的好处
Docker项目的发起人和Docker公司CTO Solomon Hykes曾认为,Docker在正确的地点、正确的时间顺应了正确的趋势——如何正确地构建应用。
在云时代,开发者创建的应用必须要能很方便地在网络上传播,也就是说应用必须脱离底层物理硬件的限制;同时必须是“任何时间、任何地点”可获取的。因此,开发者需要一种新型的创建分布式应用程序的方式,快速分发和部署,这正是Docker所能够提供的最大优势。
举个简单的例子,假设用户试图基于最常见的LAMP(Linux+Apache+MySQL+PHP)组合来构建一个网站。按照传统的做法,首先,需要安装Apache、MySQL和PHP以及它们各自运行所依赖的环境;之后分别对它们进行配置(包括创建合适的用户、配置参数等);经过大量的操作后,还需要进行功能测试,看是否工作正常;如果不正常,则进行调试追踪,意味着更多的时间代价和不可控的风险。可以想象,如果应用数目变多,事情会变得更加难以处理。
更为可怕的是,一旦需要服务器迁移(例如从亚马逊云迁移到其他云),往往需要对每个应用都进行重新部署和调试。这些琐碎而无趣的“体力活”,极大地降低了工作效率。究其根源,是这些应用直接运行在底层操作系统上,无法保证同一份应用在不同的环境中行为一致。
而Docker提供了一种更为聪明的方式,通过容器来打包应用,解耦应用和运行平台。意味着迁移的时候,只需要在新的服务器上启动需要的容器就可以了,无论新旧服务器是否是同一类型的平台。这无疑将节约大量的宝贵时间,并降低部署过程出现问题的风险。
2.?Docker在开发和运维中的优势
对开发和运维(DevOps)人员来说,可能最梦寐以求的效果就是一次创建或配置,之后可以在任意地方、任意时间让应用正常运行。而Docker恰恰是可以实现这一终极目标的“瑞士军刀”。
具体说来,Docker在开发和运维过程中,具有如下几个方面的优势:
更快速的交付和部署。使用Docker,开发人员可以使用镜像来快速构建一套标准的开发环境;开发完成之后,测试和运维人员可以直接使用完全相同环境来部署代码。只要开发测试过的代码,就可以确保在生产环境无缝运行。Docker可以快速创建和删除容器,实现快速迭代,大量节约开发、测试、部署的时间。并且,整个过程全程可见,使团队更容易理解应用的创建和工作过程。
更高效的资源利用。Docker容器的运行不需要额外的虚拟化管理程序(Virtual Machine Manager,VMM,以及Hypervisor)支持,它是内核级的虚拟化,可以实现更高的性能,同时对资源的额外需求很低。跟传统虚拟机方式相比,要提高一到两个数量级。
更轻松的迁移和扩展。Docker容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、个人电脑、服务器等,同时支持主流的操作系统发行版本。这种兼容性让用户可以在不同平台之间轻松地迁移应用。
更简单的更新管理。使用Dockerf?ile,只需要小小的配置修改,就可以替代以往大量的更新工作。并且所有修改都以增量的方式被分发和更新,从而实现自动化并且高效的容器管理。
3.?Docker与虚拟机比较
作为一种轻量级的虚拟化方式,Docker在运行应用上与传统的虚拟机方式相比具有显著优势:
Docker容器很快,启动和停止可以在秒级实现,而传统的虚拟机方式需要数分钟。
Docker容器对系统资源需求很少,一台主机上可以同时运行数千个Docker容器(在IBM服务器上已经实现了同时运行10K量级的容器实例)。
Docker通过类似Git设计理念的操作来方便用户获取、分发和更新应用镜像,存储复用,增量更新。
Docker通过Dockerf?ile支持灵活的自动化创建和部署机制,提高工作效率,使流程标准化。
Docker容器除了运行其中应用外,基本不消耗额外的系统资源,保证应用性能的同时,尽量减小系统开销。传统虚拟机方式运行N个不同的应用就要起N个虚拟机(每个虚拟机需要单独分配独占的内存、磁盘等资源),而Docker只需要启动N个隔离的“很薄的”容器,并将应用放进容器内即可。应用获得的是接近原生的运行性能。
当然,在隔离性方面,传统的虚拟机方式提供的是相对封闭的隔离。但这并不意味着Docker就不安全,Docker利用Linux系统上的多种防护技术实现了严格的隔离可靠性,并且可以整合众多安全工具。从1.3.0版本开始,Docker重点改善了容器的安全控制和镜像的安全机制,极大提高了使用Docker的安全性。在已知的大规模应用中,目前尚未出现值得担忧的安全隐患。
表1-1总结了使用Docker容器技术与传统虚拟机技术的特性比较,可见容器技术在很多应用场景下都具有巨大的优势。
表1-1 Docker容器技术与传统虚拟机技术的特性比较
特  性 容  器 虚拟机
启动速度 秒级 分钟级
性能 接近原生 较弱
内存代价 很小 较多
硬盘使用 一般为MB 一般为GB
运行密度 单机支持上千个容器 一般几十个
隔离性 安全隔离 完全隔离
迁移性 优秀 一般

1.3 Docker与虚拟化
虚拟化(Virtualization)技术是一个通用的概念,在不同领域有不同的理解。在计算领域,一般指的是计算虚拟化(Computing Virtualization),或通常说的服务器虚拟化。维基百科上的定义如下:“虚拟化是一种资源管理技术,是将计算机的各种实体资源,如服务器、网络、内存及存储等,予以抽象、转换后呈现出来,打破实体结构间的不可切割的障碍,使用户可以比原本的组态更好的方式来应用这些资源。”
可见,虚拟化的核心是对资源的抽象,目标往往是为了在同一个主机上同时运行多个系统或应用,从而提高系统资源的利用率,并且带来降低成本、方便管理和容错容灾等好处。
从大类上分,虚拟化技术可分为基于硬件的虚拟化和基于软件的虚拟化。其中,真正意义上的基于硬件的虚拟化技术不多见,少数如网卡中的单根多IO虚拟化(Single Root I/O Virtualization and Sharing Specif?ication,SR-IOV)等技术,也超出了本书的讨论范畴。
基于软件的虚拟化从对象所在的层次,又可以分为应用虚拟化和平台虚拟化(通常说的虚拟机技术即属于这个范畴)。其中,前者一般指的是一些模拟设备或诸如Wine这样的软件。后者又可以细分为如下几个子类:
完全虚拟化。虚拟机模拟完整的底层硬件环境和特权指令的执行过程,客户操作系统无需进行修改。例如IBM p和z系列的虚拟化、VMware Workstation、VirtualBox、QEMU等。
硬件辅助虚拟化。利用硬件(主要是CPU)辅助支持(目前x86体系结构上可用的硬件辅助虚拟化技术包括Intel-VT和AMD-V)处理敏感指令来实现完全虚拟化的功能,客户操作系统无需修改,例如VMware Workstation、Xen、KVM。
部分虚拟化。只针对部分硬件资源进行虚拟化,客户操作系统需要进行修改。现在有些虚拟化技术的早期版本仅支持部分虚拟化。
准虚拟化(paravirtualization)。部分硬件接口以软件的形式提供给客户机操作系统,客户操作系统需要进行修改,例如早期的Xen。
操作系统级虚拟化。内核通过创建多个虚拟的操作系统实例(内核和库)来隔离不同的进程。容器相关技术即在这个范畴。
可见,Docker以及其他容器技术,都属于操作系统虚拟化这个范畴,操作系统虚拟化最大的特点就是不需要额外的supervisor支持。
Docker虚拟化方式之所以有众多优势,这与操作系统虚拟化技术自身的设计和实现是分不开的。
图1-2比较了Docker和常见的虚拟化方式的不同之处。

图1-2 Docker和传统的虚拟化方式的不同之处
传统方式是在硬件层面实现虚拟化,需要有额外的虚拟机管理应用和虚拟机操作系统层。Docker容器是在操作系统层面上实现虚拟化,直接复用本地主机的操作系统,因此更加轻量级。
1.4 本章小结
本章介绍了容器虚拟化的基本概念、Docker的诞生及发展历史,以及容器在云时代应用分发场景下的巨大优势。
与传统的虚拟机相比,容器虚拟化方式在很多场景下都有极为明显的优势。无论是系统管理员、应用开发人员、测试人员以及运维管理人员,都应该尽快掌握Docker,尽早享受其带来的巨大便利。
后续章节,笔者将结合实践案例具体介绍Docker的安装、使用,让我们一起开启精彩的Docker之旅。





第2章
核心概念与安装配置
本章首先介绍Docker的三大核心概念。
镜像(Image)
容器(Container)
仓库(Repository)
只有理解了这三个核心概念,才能顺利地理解Docker容器的整个生命周期。
随后,笔者将介绍如何在常见的操作系统平台上安装Docker,包括Ubuntu、CentOS、MacOS和Windows等主流操作系统平台。
2.1 核心概念
Docker的大部分操作都围绕着它的三大核心概念——镜像、容器和仓库而展开。因此,准确把握这三大核心概念对于掌握Docker技术尤为重要。
1.?Docker镜像
Docker镜像类似于虚拟机镜像,可以将它理解为一个只读的模板。例如,一个镜像可以包含一个基本的操作系统环境,里面仅安装了Apache应用程序(或用户需要的其他软件)。可以把它称为一个Apache镜像。
镜像是创建Docker容器的基础。通过版本管理和增量的文件系统,Docker提供了一套十分简单的机制来创建和更新现有的镜像,用户甚至可以从网上下载一个已经做好的应用镜像,并直接使用。
2.?Docker容器
Docker容器类似于一个轻量级的沙箱,Docker利用容器来运行和隔离应用。容器是从镜像创建的应用运行实例。可以将其启动、开始、停止、删除,而这些容器都是彼此相互隔离的、互不可见的。
可以把容器看做是一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络空间等)以及运行在其中的应用程序打包而成的盒子。
镜像自身是只读的。容器从镜像启动的时候,会在镜像的最上层创建一个可写层。
3.?Docker仓库
Docker仓库类似于代码仓库,它是Docker集中存放镜像文件的场所。
有时候会看到有资料将Docker仓库和仓库注册服务器(Registry)混为一谈,并不严格区分。实际上,仓库注册服务器是存放仓库的地方,其上往往存放着多个仓库。每个仓库集中存放某一类镜像,往往包括多个镜像文件,通过不同的标签(tag)来进行区分。例如存放Ubuntu操作系统镜像的仓库称为Ubuntu仓库,其中可能包括14.04、12.04等不同版本的镜像。仓库注册服务器的示例如图2-1所示。
根据所存储的镜像公开分享与否,Docker仓库可以分为公开仓库(Public)和私有仓库(Private)两种形式。目前,最大的公开仓库是官方提供的Docker Hub,其中存放了数量庞大的镜像供用户下载。国内不少云服务提供商(如时速云、阿里云等)也提供了仓库的本地源,可以提供稳定的国内访问。
当然,用户如果不希望公开分享自己的镜像文件,Docker也支持用户在本地网络内创建一个只能自己访问的私有仓库。当用户创建了自己的镜像之后就可以使用push命令将它上传到指定的公有或者私有仓库。这样用户下次在另外一台机器上使用该镜像时,只需要将其从仓库上pull下来就可以了。
可以看出,Docker利用仓库管理镜像的设计理念与Git非常相似,实际上在理念设计上借鉴了Git的很多优秀思想。
2.2 安装Docker
Docker在主流的操作系统和云平台上都可以使用,包括Linux操作系统(如Ubuntu、Debian、CentOS、Redhat等)、MacOS操作系统和Windows操作系统,以及AWS等云平台。
用户可以访问Docker官网的Get Docker(https://www.docker.com/products/overview)页面,查看获取Docker的方式,以及Docker支持的平台类型,如图2-2所示。

图2-2 获取Docker
在Get Docker页面,我们可以看到目前Docker支持Docker Platform、Docker Hub、Docker Cloud和Docker DataCenter。
Docker Platform:支持在桌面系统或云平台安装Docker;
DockerHub:官方提供的云托管服务,可以提供公有或私有的镜像仓库;
DockerCloud:官方提供的容器云服务,可以完成容器的部署与管理,可以完整地支持容器化项目,还有CI、CD功能;
Docker DataCenter:提供企业级的简单安全弹性的容器集群编排和管理。
笔者推荐尽量使用Linux操作系统来运行Docker,因为目前Linux操作系统对Docker的支持是原生的,使用体验最好。
2.2.1 Ubuntu环境下安装Docker
1.?系统要求
Docker目前只能运行在64位平台上,并且要求内核版本不低于3.10,实际上内核越新越好,过低的内核版本容易造成功能不稳定。
用户可以通过如下命令检查自己的内核版本详细信息:
$ uname -a
Linux Host 3.16.0-43-generic #58~14.04.1-Ubuntu SMP Mon Jun 22 10:21:20 UTC 
    2015 x86_64 x86_64 x86_64 GNU/Linux
或者:
$ cat /proc/version
Linux version 3.16.0-43-generic (buildd@brownie) (gcc version 4.8.2 (Ubuntu 
    4.8.2-19ubuntu1) ) #58~14.04.1-Ubuntu SMP Mon Jun 22 10:21:20 UTC 2015
Docker目前支持的最低Ubuntu版本为12.04 LTS,但实际上从稳定性上考虑,推荐至少使用14.04 LTS版本。
如果使用12.04 LTS版本,首先要更新系统内核和安装可能需要的软件包,包括:
linux-image-generic-lts-trusty(必备)
linux-headers-generic-lts-trusty(必备)
xserver-xorg-lts-trusty(带图形界面时必备)
libgl1-mesa-glx-lts-trusty(带图形界面时必备)
另外,为了让Docker使用aufs存储,推荐安装linux-image-extra软件包。
$ sudo apt-get install -y linux-image-extra-$(uname -r)
Ubuntu发行版中,LTS(Long-Term-Support)意味着更稳定的功能和更长期(目前为5年)的升级支持,生产环境中尽量使用LTS版本。
2.?添加镜像源
首先需要安装apt-transport-https包支持HTTPS协议的源:
$ sudo apt-get install -y apt-transport-https
添加源的gpg密钥:
$ sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 
    58118E89F3A912897C070ADBF76221572C52609D
获取当前操作系统的代号:
$ lsb_release -c
Codename:       trusty
一般情况下,12.04(LTS)代号为precise,14.04(LTS)代号为trusty,15.04代号为vivid,15.10代号为wily。这里获取的代号为trusty。
接下来就可以添加Docker的官方apt软件源了。通过下面的命令创建/etc/apt/sources.list.d/docker.list文件,并写入源的地址内容。非trusty版本的系统注意修改为自己对应的代号:
$ sudo cat <<EOF > /etc/apt/sources.list.d/docker.list
deb https://apt.dockerproject.org/repo ubuntu-trusty main
EOF
添加成功后,更新apt软件包缓存:
$ sudo apt-get update
3.?开始安装Docker
在成功添加源之后,就可以安装最新版本的Docker了,软件包名称为docker-engine:
$ sudo apt-get install -y docker-engine
如果系统中存在较旧版本的Docker(lxc-docker),会提示是否先删除,选择“是”即可。
除了基于手动添加软件源的方式,也可以使用官方提供的脚本来自动化安装Docker:
$ sudo curl -sSL https://get.docker.com/ | sh
安装成功后,启动docker服务:
$ sudo service docker start
2.2.2 CentOS环境下安装Docker
系统的要求与Ubuntu情况下类似:64位操作系统,内核版本至少为3.10。
Docker目前支持CentOS 6.5及以后的版本,推荐使用CentOS 7系统。
首先,也是要添加yum软件源:
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
之后更新yum软件源缓存,并安装docker-engine:
$ sudo yum update
$ sudo yum install -y docker-engine
对于CentOS 7系统,CentOS-Extras源中已内置Docker,如果已经配置了CentOS-Extras源,可以直接通过上面的yum命令进行安装。
2.2.3 通过脚本安装
用户还可以使用官方提供的shell脚本来在Linux系统(目前支持Ubuntu、Debian、Oracleserver、Fedora、Centos、OpenSuse、Gentoo等常见发行版)上安装Docker的最新正式版本,该脚本会自动检测系统信息并进行相应配置:
$ curl -fsSL https://get.docker.com/ | sh
或者:
$ wget -qO- https://get.docker.com/ | sh
如果想尝鲜使用最新功能,可以使用下面的脚本来安装预发布版本。但要注意,预发布版本往往意味着功能还不够稳定,不要在生产环境中使用:
$ curl -fsSL https://test.docker.com/ | sh
另外,也可以从github.com/docker/docker/releases找到所有的发行版本信息和二进制包,自行下载使用。
2.2.4 Mac OS环境下安装Docker
Docker官方非常重视Docker在Mac环境下的易用性。目前Docker支持原生Mac客户端,内置图形界面,支持自动升级。此客户端与Mac OS X的原生虚拟化深度结合,摒弃了之前安装VirtualBox(即Docker Toolbox)的简单粗暴的做法。我们先从官方默认的Docker for Mac开始。
1.?Docker for Mac
第一步,下载安装包。访问https://docs.docker.com/docker-for-mac/下载页面。目前Docker for Mac分为稳定版和Beta版两种更新通道,我们可以按需选择。下载完成后,双击安装包,如图2-3所示。

图2-3 下载后打开安装包
第二步,开始安装。将Docker.app拖曳至Applications文件夹,即可完成安装,如图2-4所示。

图2-4 安装Docker到Applications文件夹
第三步,运行Docker for Mac。在欢迎窗口点击“Next”,如图2-5所示。

图2-5 欢迎窗口
允许Docker获得系统权限,它需要将Mac网卡链接至Docker app。点击“OK”后输入系统管理员密码,如图2-6所示。

图2-6 运行Docker for Mac
此时系统状态栏会出现Docker的Icon图标,点击后如果出现“Docker is running!”,则说明安装成功。
第四步,验证Docker安装。打开终端控制器或其他系统命令行,执行docker version命令。
$ docker version
Client:
    Version:      1.12.0
    API version:  1.24
    Go version:   go1.6.3
    Git commit:   8eab29e
    Built:        Thu Jul 28 21:15:28 2016
    OS/Arch:      darwin/amd64

Server:
    Version:      1.12.0
    API version:  1.24
    Go version:   go1.6.3
    Git commit:   8eab29e
    Built:        Thu Jul 28 21:15:28 2016
    OS/Arch:      linux/amd64
如果我们看到Client和Server均有输出,则说明Docker for Mac已经正常启动。如果我们看到报错:“Cannot connect to the Docker daemon. Is the docker daemon running on this host?”,则说明Docker for Mac没有启动或启动失败。
下面启动一个Nginx容器,检查能正确获取镜像并运行:
$ docker run -d -p 80:80 --name webserver nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
51f5c6a04d83: Pull complete
a3ed95caeb02: Pull complete
51d229e136d0: Pull complete
bcd41daec8cc: Pull complete
Digest: 
sha256:0fe6413f3e30fcc5920bc8fa769280975b10b1c26721de956e1428b9e2f29d04
Status: Downloaded newer image for nginx:latest
34bcd01998a76f67b1b9e6abe5b7db5e685af325d6fafb1acd0ce84e81e71e5d
然后使用docker ps指令查看当前运行的容器:
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED
STATUS              PORTS                         NAMES
34bcd01998a7        nginx               "nginx -g 'daemon off"   2 minutes ago
Up 2 minutes        0.0.0.0:80->80/tcp, 443/tcp   webserver
可见Nginx容器已经在0.0.0.0:80启动,并映射了80端口,下面我们打开浏览器访问此地址,如图2-7所示。
第五步,常用配置设定。首先,点击系统状态栏的Docker图标,会出现操作菜单,如图2-8所示。
      
         图2-7 允许访问系统权限          ?  图2-8 Docker菜单
然后,点击Preferences,进入标准配置页面,我们可以设置是否自动启动与更新,设置备份工具Time Machine是否备份VM,还可以配置Docker使用的CPU数、内存容量,如图2-9所示。
点击进入Advanced进阶配置。为了更好地使用Docker Hub,我们可以使用Registry镜像站点进行加速。点击+后,加入镜像站点配置。这里还可以配置HTTP代理服务器,如图2-10所示。
点击进入File Sharing标签页,此处可以配置挂载至容器中的本地目录。点击+后可以继续添加本地目录,如图2-11所示。
      
图2-9 标准配置页面                图2-10 高级配置页面
点击进入Privacy标签页,此处可以配置隐私选项,如是否发送使用信息,以及是否发送程序崩溃报告,如图2-12所示。
      
图2-11 文件分享配置页面             ? 图2-12 隐私配置页面 
2.?Docker Toolbox
在Mac OS X操作系统上安装Docker,除了Docker for Mac的原生方式之外,还可以使用官方提供的Docker ToolBox工具。
首先前往https://www.docker.com/products/docker-toolbox下载对应版本的ToolBox。目前Docker支持的Mac OS X版本为10.6+。如图2-13所示。

图2-13 ToolBox安装页面
双击运行安装包。这个过程将安装一个VirtualBox虚拟机,内置了Docker Engine、Compose、Machine、Kitematic等管理工具。安装成功后,找到Boot2Docker并运行它。如图2-14所示。

图2-14 Boot2Docker页面
现在进行Boot2Docker的初始化:
$ boot2docker init
$ boot2docker start
$ $(boot2docker shellinit)
将看到虚拟机在命令行窗口中启动运行。当虚拟机初始化完毕后,可以使用boot2docker stop和boot2docker start来控制它。
注意,如果在命令行中看到如下提示信息:
To connect the Docker client to the Docker daemon, please set: export DOCKER_
    HOST=tcp://192.168.59.103:2375
可以执行提示信息中的语句:export DOCKER_HOST=tcp://192.168.59.103:2375。此语句的作用是在系统环境变量中设置Docker的主机地址。
2.2.5 Windows环境下安装Docker
目前Docker可以通过虚拟机方式来支持Windows 7.1和8,只要平台CPU支持硬件虚拟化特性即可。如果无法确定自己计算机的CPU是否支持该特性也无需担心,实际上,目前市面上主流的CPU都早已支持了硬件虚拟化特性。
对于Windows 10用户,Docker官方提供了原生虚拟化应用Docker for Windows。详情见:https://docs.docker.com/windows/step_one/。目前国内Windows 7还是主导地位的版本,所以下面主要讲解如何在Windows 7环境下安装Docker环境。
由于Docker引擎使用了Linux内核特性,所以如果要在Windows 10之外的Windows上运行,需要额外使用一个虚拟机来提供Linux支持。这里推荐使用Boot2Docker工具,它会首先安装一个经过加工与配置的轻量级虚拟机,然后在其中运行Docker。主要步骤如下:
首先,从https://docs.docker.com/installation/windows/下载最新官方Docker for Windows Installer。双击打开Installer。这个过程将安装VirtualBox、MSYS-git、boot2docker Linux ISO镜像,以及Boot2Docker管理工具。如图2-15所示。

图2-15 Docker for Windows Installer
最后,打开桌面的Boot2Docker Start程序,或者Program Files\Boot2Docker for Windows。此初始化脚本在第一次运行时需要输入一个SSH Key Passphrase(用于SSH密钥生成的口令)。读者可以自行设定,也可以直接按回车键跳过此设定。如图2-16所示。

图2-16 Boot2Docker安装器
此时Boot2Docker Start程序将连接至虚拟机中的Shell会话,Docker已经运行起来了!
2.3 配置Docker服务
为了避免每次使用docker命令都要用特权身份,可以将当前用户加入安装中自动创建的docker用户组:
$ sudo usermod -aG docker USER_NAME
用户更新组信息后,退出并重新登录后即可生效。
另外,Docker服务支持多种启动参数。以Ubuntu 14.04系统为例,Docker服务的默认配置文件为/etc/default/docker,可以通过修改其中的DOCKER_OPTS来修改服务启动的参数,例如,下一行代码让Docker服务可以通过本地2375端口接收来自外部的请求:
DOCKER_OPTS="$DOCKER_OPTS -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"
修改之后,通过service命令来重启Docker服务:
$ sudo service docker restart
一般情况下,Docker服务的管理脚本为/etc/init.d/docker,通过查看其中的内容,发现主要是将Docker进程的id写入/var/run/docker.pid文件,以及通过ulimit调整系统的资源限制。
如果是通过较新的upstart工具来管理服务,则管理服务配置文件在/etc/init/docker.conf。
另外,对于CentOS、Redhat等系统,服务可能是通过systemd来管理,与此略有不同,可以查阅systemd相关手册。
例如,需要通过systemctl命令来管理Docker服务:
$ sudo systemctl start docker.service
此外,如果服务工作不正常,可以通过查看Docker服务的日志信息来确定问题,例如在Ubuntu系统上日志文件可能为/var/log/upstart/docker.log:
$ sudo tail /var/log/upstart/docker.log
每次重启Docker服务后,可以通过查看Docker版本信息,确保服务已经正常运行:
$ docker version
Client:
    Version:      1.12.0
    API version:  1.24
    Go version:   go1.6.3
    Git commit:   8eab29e
    Built:        Thu Jul 28 21:15:28 2016
    OS/Arch:      darwin/amd64

Server:
    Version:      1.12.0
    API version:  1.24
    Go version:   go1.6.3
    Git commit:   8eab29e
    Built:        Thu Jul 28 21:15:28 2016
    OS/Arch:      linux/amd64
2.4 推荐实践环境
从稳定性上考虑,本书推荐的实践环境的操作系统是Ubuntu 14.04.3 LTS系统,带有linux-image-3.16.0-71-generic内核。Docker版本为最新的1.12稳定版本。不同版本的API会略有差异,推荐根据需求选择较新的稳定版本。另外,如无特殊说明,默认数据网段地址范围为10.0.0.0/24,管理网段地址范围为192.168.0.0/24。
执行命令代码中以$开头的,表示为普通用户;以#开头的,表示为特权用户(root)。如果用户已经添加到了docker用户组(参考上一小节),大部分时候都无需管理员权限,否则需要在命令前使用sudo来临时提升权限。
部分命令执行结果输出内容较长的,只给出了输出的关键部分。读者可根据自己的实际情况,搭建类似的环境。
2.5 本章小结
本章介绍了Docker的三大核心概念:镜像、容器和仓库。在后面的实践中,读者会感受到,基于三大核心概念所构建的高效工作流程,正是Docker从众多容器虚拟化方案中脱颖而出的重要原因。实际上,Docker的工作流也并非凭空创造的,很大程度上参考了Git和Github的设计理念,从而为应用分发和团队合作都带来了众多优势。
在后续章节,笔者将具体讲解围绕这三大核心概念的Docker操作命令。





第3章
使用Docker镜像
镜像(image)是Docker三大核心概念中最为重要的,自Docker诞生之日起“镜像”就是相关社区最为热门的关键词。
Docker运行容器前需要本地存在对应的镜像,如果镜像没保存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。
本章将介绍围绕镜像这一核心概念的具体操作,包括如何使用pull命令从Docker Hub仓库中下载镜像到本地,如何查看本地已有的镜像信息和管理镜像标签,如何在远端仓库使用search命令进行搜索和过滤,如何删除镜像标签和镜像文件,如何创建用户定制的镜像并且保存为外部文件。最后,还介绍如何往Docker Hub仓库中推送自己的镜像。
一份非官方研究报告表明,image一直是Docker官方社区(2014~2016年)和StackOverFlow Docker板块(2013~2016年)的年度热词。
3.1 获取镜像
镜像是运行容器的前提,官方的Docker Hub网站已经提供了数十万个镜像供大家开放下载。
可以使用docker pull命令直接从Docker Hub镜像源来下载镜像。该命令的格式为docker pull NAME[:TAG]。其中,NAME是镜像仓库的名称(用来区分镜像),TAG是镜像的标签(往往用来表示版本信息)。通常情况下,描述一个镜像需要包括“名称+标签”信息。
例如,获取一个Ubuntu 14.04系统的基础镜像可以使用如下的命令:
$ docker pull ubuntu:14.04
14.04: Pulling from library/ubuntu
6c953ac5d795: Pull complete
3eed5ff20a90: Pull complete
f8419ea7c1b5: Pull complete
51900bc9e720: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:97421885f3da3b23f52eeddcaa9f8f91172a8ac3cd5d3cd40b51c7aad09f66cc
Status: Downloaded newer image for ubuntu:14.04
对于Docker镜像来说,如果不显式指定TAG,则默认会选择latest标签,这会下载仓库中最新版本的镜像。
下面的例子将从Docker Hub的Ubuntu仓库下载一个最新的Ubuntu操作系统的镜像。
$ docker pull ubuntu
Using default tag: latest
latest: Pulling from library/ubuntu
5ba4f30e5bea: Pull complete
9d7d19c9dc56: Pull complete
ac6ad7efd0f9: Pull complete
e7491a747824: Pull complete
a3ed95caeb02: Pull complete
Digest: sha256:46fb5d001b88ad904c5c732b086b596b92cfb4a4840a3abd0e35dbb6870585e4
Status: Downloaded newer image for ubuntu:latest
该命令实际上下载的就是ubuntu:latest镜像。
一般来说,镜像的latest标签意味着该镜像的内容会跟踪最新的非稳定版本而发布,内容是不稳定的。当前Ubuntu最新的发行版本为16.04,latest镜像实际上就是16.04镜像,用户可以下载ubuntu:16.04镜像并查看,两者的数字摘要值是一致的。从稳定性上考虑,不要在生产环境中忽略镜像的标签信息或使用默认的latest标记的镜像。
下载过程中可以看出,镜像文件一般由若干层(layer)组成,6c953ac5d795这样的串是层的唯一id(实际上完整的id包括256比特,由64个十六进制字符组成)。使用docker pull命令下载时会获取并输出镜像的各层信息。当不同的镜像包括相同的层时,本地仅存储层的一份内容,减小了需要的存储空间。
读者可能会想到,在使用不同的镜像仓库服务器的情况下,可能会出现镜像重名的情况。
严格地讲,镜像的仓库名称中还应该添加仓库地址(即registry,注册服务器)作为前缀,只是我们默认使用的是Docker Hub服务,该前缀可以忽略。
例如,docker pull ubuntu:14.04命令相当于docker pull registry.hub.docker.com/ubuntu:14.04命令,即从默认的注册服务器Docker Hub Registry中的ubuntu仓库来下载标记为14.04的镜像。
如果从非官方的仓库下载,则需要在仓库名称前指定完整的仓库地址。例如从网易蜂巢的镜像源来下载ubuntu:14.04镜像,可以使用如下命令,此时下载的镜像名称为hub.c.163.com/public/ubuntu:14.04:
$ docker pull hub.c.163.com/public/ubuntu:14.04
pull子命令支持的选项主要包括:
-a, --all-tags=true|false:是否获取仓库中的所有镜像,默认为否。
下载镜像到本地后,即可随时使用该镜像了,例如利用该镜像创建一个容器,在其中运行bash应用,执行ping localhost命令:
$ docker run -it ubuntu:14.04 bash
root@9c74026df12a:/# ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.023 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.018 ms
^C
--- localhost ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.018/0.033/0.058/0.017 ms
root@9c74026df12a:/# exit
exit
3.2 查看镜像信息
1.?使用images命令列出镜像
使用docker images命令可以列出本地主机上已有镜像的基本信息。
例如,下面的命令列出了上一小节中下载的镜像信息:
$ docker images
REPOSITORY               TAG            IMAGE ID        CREATED         SIZE
ubuntu                   16.04          2fa927b5cdd3    2 weeks ago     122 MB
ubuntu                   latest         2fa927b5cdd3    2 weeks ago     122 MB
ubuntu                   14.04          8f1bd21bd25c    2 weeks ago     188 MB
在列出的信息中,可以看到以下几个字段信息。
来自于哪个仓库,比如ubuntu仓库用来保存ubuntu系列的基础镜像;
镜像的标签信息,比如14.04、latest用来标注不同的版本信息。标签只是标记,并不能标识镜像内容;
镜像的ID(唯一标识镜像),如ubuntu:latest和ubuntu:16.04镜像的ID都是2fa927b5cdd3,说明它们目前实际上指向同一个镜像;
创建时间,说明镜像最后的更新时间;
镜像大小,优秀的镜像往往体积都较小。
其中镜像的ID信息十分重要,它唯一标识了镜像。在使用镜像ID的时候,一般可以使用该ID的前若干个字符组成的可区分串来替代完整的ID。
TAG信息用来标记来自同一个仓库的不同镜像。例如ubuntu仓库中有多个镜像,通过TAG信息来区分发行版本,包括10.04、12.04、12.10、13.04、14.04、16.04等标签。
镜像大小信息只是表示该镜像的逻辑体积大小,实际上由于相同的镜像层本地只会存储一份,物理上占用的存储空间会小于各镜像的逻辑体积之和。
images子命令主要支持如下选项,用户可以自行进行尝试。
-a, --all=true|false:列出所有的镜像文件(包括临时文件),默认为否;
--digests=true|false:列出镜像的数字摘要值,默认为否;
-f, --filter=[]:过滤列出的镜像,如dangling=true只显示没有被使用的镜像;也可指定带有特定标注的镜像等;
--format="TEMPLATE":控制输出格式,如.ID代表ID信息,.Repository代表仓库信息等;
--no-trunc=true|false:对输出结果中太长的部分是否进行截断,如镜像的ID信息,默认为是;
-q, --quiet=true|false:仅输出ID信息,默认为否。
其中,对输出结果进行控制的选项如-f, --filter=[]、--no-trunc=true|false、
-q, --quiet=true|false等,大部分子命令都支持。
更多子命令选项还可以通过man docker-images来查看。
2.?使用tag命令添加镜像标签
为了方便在后续工作中使用特定镜像,还可以使用docker tag命令来为本地镜像任意添加新的标签。例如添加一个新的myubuntu:latest镜像标签:
$ docker tag ubuntu:latest myubuntu:latest
再次使用docker images列出本地主机上镜像信息,可以看到多了一个拥有myubuntu: latest标签的镜像:
$ docker images
REPOSITORY       TAG       IMAGE ID          CREATED         SIZE
ubuntu           16.04     2fa927b5cdd3      2 weeks ago     122 MB
ubuntu           latest    2fa927b5cdd3      2 weeks ago     122 MB
myubuntu         latest    2fa927b5cdd3      2 weeks ago     122 MB
ubuntu           14.04     8f1bd21bd25c      2 weeks ago     188 MB
之后,用户就可以直接使用myubuntu:latest来表示这个镜像了。
细心的读者可能注意到,这些myubuntu:latest镜像的ID跟ubuntu:latest完全一致。它们实际上指向同一个镜像文件,只是别名不同而已。docker tag命令添加的标签实际上起到了类似链接的作用。
3.?使用inspect命令查看详细信息
使用docker inspect命令可以获取该镜像的详细信息,包括制作者、适应架构、各层的数字摘要等:
$ docker inspect ubuntu:14.04
[
    {
        "Id": "sha256:8f1bd21bd25c3fb1d4b00b7936a73a0664f932e11406c48a0ef19d82fd0b7342",
        "RepoTags": [
            "ubuntu:14.04"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "",
        "Created": "2016-05-27T14:13:04.103044105Z",
        "Container": "eb8c67a3bff6e93658d18ac14b3a2134488c140a1ae1205c0cfdfd49f087113f",
        "ContainerConfig": {
            "Hostname": "fff5562e8198",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) CMD [\"/bin/bash\"]"
            ],
            "Image": "f9cdf71c33f14c7af4b75b651624e9ac69711630e21ceb289f69e0300e90c57d",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "1.9.1",
        "Author": "",
        "Config": {
            "Hostname": "fff5562e8198",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [],
            "Cmd": [
                "/bin/bash"
            ],
            "Image": "f9cdf71c33f14c7af4b75b651624e9ac69711630e21ceb289f69e0300e90c57d",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 187957543,
        "VirtualSize": 187957543,
        "GraphDriver": {
            "Name": "aufs",
            "Data": null
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:a7e1c363defb1f80633f3688e945754fc4c8f1543f07114befb5e0175d569f4c",
                "sha256:dc109d4b4ccf69361d29292fb15e52707507b520aba8cd43a564182f26725d74",
                "sha256:9f7ab087e6e6574225f863b6013579a76bd0c80c92fefe7aea92c4207b6486cb",
                "sha256:6f8be37bd578bbabe570b0181602971b0ea3509b79a1a3dd5528a4e3fc33dd6f",
                "sha256:5f70bf18a086007016e948b04aed3b82103a36bea41755b6cddfaf10ace3c6ef"
            ]
        }
    }
]
返回的是一个JSON格式的消息,如果我们只要其中一项内容时,可以使用参数-f来指定,例如,获取镜像的Architecture:
$ docker inspect -f {{".Architecture"}}
amd64
4.?使用history命令查看镜像历史
既然镜像文件由多个层组成,那么怎么知道各个层的内容具体是什么呢?这时候可以使用history子命令,该命令将列出各层的创建信息。
例如,查看ubuntu:14.04镜像的创建过程,可以使用如下命令:
$ docker history ubuntu:14.04
IMAGE         CREATED      CREATED BY                                     SIZE COMMENT
8f1bd21bd25c  2 weeks ago  /bin/sh -c #(nop) CMD ["/bin/bash"]            0 B
<missing>     2 weeks ago  /bin/sh -c sed -i 's/^#\s*\(deb.*universe\)$/  1.895 kB
<missing>     2 weeks ago  /bin/sh -c rm -rf /var/lib/apt/lists/*         0 B
<missing>     2 weeks ago  /bin/sh -c set -xe   && echo '#!/bin/sh' > /u  194.5 kB
<missing>     2 weeks ago  /bin/sh -c #(nop) ADD file:aca501360d0937bc49  187.8 MB
注意过长的命令被自动截断了,可以使用前面提到的--no-trunc选项来输出完整
命令。
3.3 搜寻镜像
使用docker search命令可以搜索远端仓库中共享的镜像,默认搜索官方仓库中的镜像。用法为docker search TERM,支持的参数主要包括:
--automated=true|false:仅显示自动创建的镜像,默认为否;
--no-trunc=true|false:输出信息不截断显示,默认为否;
-s, --stars=X:指定仅显示评价为指定星级以上的镜像,默认为0,即输出所有镜像。
例如,搜索所有自动创建的评价为1+的带nginx关键字的镜像,如下所示:
$ docker search --automated -s 3 nginx
NAME                     DESCRIPTION           STARS     OFFICIAL   AUTOMATED
jwilder/nginx-proxy      Automated Nginx reverse proxy for docker c...  670  [OK]
richarvey/nginx-php-fpm  Container running Nginx + PHP-FPM capable ...  206  [OK]
million12/nginx-php      Nginx + PHP-FPM 5.5, 5.6, 7.0 (NG), CentOS...   67  [OK]
maxexcloo/nginx-php      Docker framework container with Nginx and ...   57  [OK]
webdevops/php-nginx      Nginx with PHP-FPM                              38  [OK]
h3nrik/nginx-ldap        NGINX web server with LDAP/AD, SSL and pro...   27  [OK]
bitnami/nginx            Bitnami nginx Docker Image                      18  [OK]
maxexcloo/nginx          Docker framework container with Nginx inst...   7   [OK]
million12/nginx          Nginx: extensible, nicely tuned for better...   4   [OK]
webdevops/nginx          Nginx container                                 3   [OK]
ixbox/nginx              Nginx on Alpine Linux.                          3   [OK]
evild/alpine-nginx       Minimalistic Docker image with Nginx            3   [OK]
可以看到返回了很多包含关键字的镜像,其中包括镜像名字、描述、星级(表示该镜像的受欢迎程度)、是否官方创建、是否自动创建等。
默认的输出结果将按照星级评价进行排序。
3.4 删除镜像
1.?使用标签删除镜像
使用docker rmi命令可以删除镜像,命令格式为docker rmi IMAGE [IMAGE...],其中IMAGE可以为标签或ID。
例如,要删除掉myubuntu:latest镜像,可以使用如下命令:
$ docker rmi myubuntu:latest
Untagged: myubuntu:latest
读者可能会担心,本地的ubuntu:latest镜像是否会受此命令的影响。无需担心,当同一个镜像拥有多个标签的时候,docker rmi命令只是删除该镜像多个标签中的指定标签而已,并不影响镜像文件。因此上述操作相当于只是删除了镜像2fa927b5cdd3的一个标签而已。
为保险起见,再次查看本地的镜像,发现ubuntu:latest镜像(准确地说是2fa927b5cdd3镜像)仍然存在:
$ docker images
REPOSITORY       TAG         IMAGE ID            CREATED             SIZE
ubuntu           16.04       2fa927b5cdd3        2 weeks ago         122 MB
ubuntu           latest      2fa927b5cdd3        2 weeks ago         122 MB
ubuntu           14.04       8f1bd21bd25c        2 weeks ago         188 MB
但当镜像只剩下一个标签的时候就要小心了,此时再使用docker rmi命令会彻底删除镜像。
例如删除标签为ubuntu:14.04的镜像,由于该镜像没有额外的标签指向它,执行docker rmi命令,可以看出它会删除这个镜像文件的所有层:
$ docker rmi ubuntu:14.04
Untagged: ubuntu:14.04
Deleted: sha256:8f1bd21bd25c3fb1d4b00b7936a73a0664f932e11406c48a0ef19d82fd0b7342
Deleted: sha256:8ea3b9ba4dd9d448d1ca3ca7afa8989d033532c11050f5e129d267be8de9c1b4
Deleted: sha256:7db5fb90eb6ffb6b5418f76dde5f685601fad200a8f4698432ebf8ba80757576
Deleted: sha256:19a7e879151723856fb640449481c65c55fc9e186405dd74ae6919f88eccce75
Deleted: sha256:c357a3f74f16f61c2cc78dbb0ae1ff8c8f4fa79be9388db38a87c7d8010b2fe4
Deleted: sha256:a7e1c363defb1f80633f3688e945754fc4c8f1543f07114befb5e0175d569f4c
2.?使用镜像ID删除镜像
当使用docker rmi命令,并且后面跟上镜像的ID(也可以是能进行区分的部分ID串前缀)时,会先尝试删除所有指向该镜像的标签,然后删除该镜像文件本身。
注意,当有该镜像创建的容器存在时,镜像文件默认是无法被删除的,例如,先利用ubuntu:14.04镜像创建一个简单的容器来输出一段话:
$ docker run ubuntu:14.04 echo 'hello! I am here!'
hello! I am here!
使用docker ps -a命令可以看到本机上存在的所有容器:
$ docker ps -a
CONTAINER ID   IMAGE   COMMAND   CREATED    STATUS  PORTS   NAMES
a21c0840213e        ubuntu:14.04        "echo 'hello! I am he"   About a minute 
    ago   Exited (0) About a minute ago     romantic_euler
可以看到,后台存在一个退出状态的容器,是刚基于ubuntu:14.04镜像创建的。
试图删除该镜像,Docker会提示有容器正在运行,无法删除:
$ docker rmi ubuntu:14.04
Error response from daemon: conflict: unable to remove repository reference "ubuntu:
    14.04" (must force) - container a21c0840213e is using its referenced image 
    8f1bd21bd25c
如果要想强行删除镜像,可以使用-f参数。
$ docker rmi -f ubuntu:14.04
Untagged: ubuntu:14.04
Deleted: sha256:8f1bd21bd25c3fb1d4b00b7936a73a0664f932e11406c48a0ef19d82fd0b7342
注意,通常并不推荐使用-f参数来强制删除一个存在容器依赖的镜像。正确的做法是,先删除依赖该镜像的所有容器,再来删除镜像。首先删除容器a21c0840213e:
$ docker rm a21c0840213e
再使用ID来删除镜像,此时会正常打印出删除的各层信息:
$ docker rmi 8f1bd21bd25c
Untagged: ubuntu:14.04
Deleted: sha256:8f1bd21bd25c3fb1d4b00b7936a73a0664f932e11406c48a0ef19d82fd0b7342
Deleted: sha256:8ea3b9ba4dd9d448d1ca3ca7afa8989d033532c11050f5e129d267be8de9c1b4
Deleted: sha256:7db5fb90eb6ffb6b5418f76dde5f685601fad200a8f4698432ebf8ba80757576
Deleted: sha256:19a7e879151723856fb640449481c65c55fc9e186405dd74ae6919f88eccce75
Deleted: sha256:c357a3f74f16f61c2cc78dbb0ae1ff8c8f4fa79be9388db38a87c7d8010b2fe4
Deleted: sha256:a7e1c363defb1f80633f3688e945754fc4c8f1543f07114befb5e0175d569f4c
3.5 创建镜像
创建镜像的方法主要有三种:基于已有镜像的容器创建、基于本地模板导入、基于Dockerf?ile创建。
本节将重点介绍前两种方法。最后一种基于Dockerfile创建的方法将在后续章节专门予以详细介绍。
1.?基于已有镜像的容器创建
该方法主要是使用docker commit命令。命令格式为docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]],主要选项包括:
-a, --author="":作者信息;
-c, --change=[]:提交的时候执行Dockerf?ile指令,包括CMD|ENTRYPOINT|ENV|EXPOSE|LABEL|ONBUILD|USER|VOLUME|WORKDIR等;
-m, --message="":提交消息;
-p, --pause=true:提交时暂停容器运行。
下面将演示如何使用该命令创建一个新镜像。首先,启动一个镜像,并在其中进行修改操作,例如创建一个test文件,之后退出:
$ docker run -it ubuntu:14.04 /bin/bash
root@a925cb40b3f0:/# touch test
root@a925cb40b3f0:/# exit
记住容器的ID为a925cb40b3f0。
此时该容器跟原ubuntu:14.04镜像相比,已经发生了改变,可以使用docker commit命令来提交为一个新的镜像。提交时可以使用ID或名称来指定容器:
$ docker commit -m "Added a new file" -a "Docker Newbee" a925cb40b3f0 test:0.1
9e9c814023bcffc3e67e892a235afe61b02f66a947d2747f724bd317dda02f27
顺利的话,会返回新创建的镜像的ID信息,例如9e9c814023bcffc3e67e892a235afe61b02f66a947d2747f724bd317dda02f27。
此时查看本地镜像列表,会发现新创建的镜像已经存在了:
$ docker images
REPOSITORY        TAG     IMAGE ID        CREATED           VIRTUAL SIZE
test              0.1     9e9c814023bc    4 seconds ago     188 MB
2.?基于本地模板导入
用户也可以直接从一个操作系统模板文件导入一个镜像,主要使用docker import命令。命令格式为docker import [OPTIONS] file|URL|-[REPOSITORY[:TAG]]。
要直接导入一个镜像,可以使用OpenVZ提供的模板来创建,或者用其他已导出的镜像模板来创建。OPENVZ模板的下载地址为http://openvz.org/Download/templates/precreated。
例如,下载了ubuntu-14.04的模板压缩包,之后使用以下命令导入:
$ cat ubuntu-14.04-x86_64-minimal.tar.gz | docker import - ubuntu:14.04
然后查看新导入的镜像,会发现它已经在本地存在了:
$ docker images
REPOSITORY        TAG         IMAGE ID         CREATED             VIRTUAL SIZE
ubuntu            14.04       05ac7c0b9383     17 seconds ago      215.5 MB
3.6 存出和载入镜像
用户可以使用docker save和docker load命令来存出和载入镜像。
1.?存出镜像
如果要导出镜像到本地文件,可以使用docker save命令。例如,导出本地的ubuntu: 14.04镜像为文件ubuntu_14.04.tar,如下所示:
$ docker images
REPOSITORY          TAG         IMAGE ID        CREATED         VIRTUAL SIZE
ubuntu              14.04       8f1bd21bd25c    2 weeks ago     188 MB
...
$ docker save -o ubuntu_14.04.tar ubuntu:14.04
之后,用户就可以通过复制ubuntu_14.04.tar文件将该镜像分享给他人。
2.?载入镜像
可以使用docker load将导出的tar文件再导入到本地镜像库,例如从文件ubuntu_
14.04.tar导入镜像到本地镜像列表,如下所示:
$ docker load --input ubuntu_14.04.tar
或:
$ docker load < ubuntu_14.04.tar
这将导入镜像及其相关的元数据信息(包括标签等)。导入成功后,可以使用docker images命令进行查看。
3.7 上传镜像
可以使用docker push命令上传镜像到仓库,默认上传到Docker Hub官方仓库(需要登录)。命令格式为:
docker push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]
用户在Docker Hub网站注册后可以上传自制的镜像。例如用户user上传本地的test:latest镜像,可以先添加新的标签user/test:latest,然后用docker push命令上传镜像:
$ docker tag test:latest user/test:latest
$ docker push user/test:latest
The push refers to a repository [docker.io/user/test]
Sending image list

Please login prior to push:
Username:
Password:
Email:
第一次上传时,会提示输入登录信息或进行注册。
3.8 本章小结
本章具体介绍了围绕Docker镜像的一系列重要命令操作,包括获取、查看、搜索、删除、创建、存出和载入、上传等。
镜像是使用Docker的前提,也是最基本的资源。所以,在平时的Docker使用中,要注意积累自己定制的镜像文件,并将自己创建的高质量镜像分享到社区中。
在后续章节,笔者将介绍更多对镜像进行操作的场景。

版权声明:如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:developerteam@list.alibaba-inc.com 进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:

华章出版社

官方博客
官网链接