Alan Hou的个人博客

精通Docker第三版 – 第一章 Docker概览

《精通Docker第三版》完整目录:

第一章 Docker概览
第二章 创建容器镜像
第三章 存储和发布镜像
第四章 管理容器
第五章 Docker Compose
第六章 Windows容器
第七章 Docker Machine
第八章 Docker Swarm
第九章 Docker和Kubernetes
第十章 在公有云上运行Docker
第十一章 Portainer – 一个Docker的GUI
第十二章 Docker安全
第十三章 Docker工作流
第十四章 Docker进阶

欢迎来到《精通Docker第三版》!第一章将涵盖你应该已经有所了解的Docker基础知识。但如果你尚不具备相应知识,本章将帮助你了解相关基础知识,这样学习后续章节就不会觉得困难重重。在学完本书后,你将成为Docker大神(传销即视感😂),可以在你自己的环境中实施Docker,基于它创建和维护应用。

本章中,我们将来回顾如下高级知识:

技术要求

本章中,我们将讨论如何在本地安装Docker。要实现安装,我们需要一个运行着以下任意一种操作系统的宿主机:

查看如下视频中的实操:

了解Docker

在进行Docker的安装之前,我们先来了解Docker技术所致力于解决的问题。

开发人员

Docker背后的公司总是将该程序描述为解决“在我的机器上运行正常”的问题。这个问题有一张图片总结的最好,是一张以“灾难女孩”迷因(Disaster Girl meme)为底,添加了Worked fine in dev, ops problem now(dev正常,运维躺枪)的文案,几年前开始频繁出现在 PPT、论坛和Slack频道上。虽然很搞笑,但不幸的是这也是血淋淋的现实,我自己也亲身经历过这一情况,让我们来看看这种问题究竟代表什么。

译者注:“灾难女孩”真名Zoë Roth,她在互联网上的风靡源自上图这张以火灾为背景的迷之微笑,后来被互联网上的吃瓜群众们 P 到泰坦尼克号、珍珠港等各种背景图上。原照片为其父亲所拍摄,背景中的火灾实为消防人员测试时大火。

问题

即便是在遵循DevOps最佳实践的世界里,仍然会存在开发者的工作环境与最终生产环境不匹配的情况。

例如,开发者可能使用macOS,其中的PHP版本与托管生产代码的Linux主机上的版本不匹配。即便是版本相匹配,我们还需要处理配置以及运行该PHP版本整体环境的不同,举例来说,一个潜在的问题是要处理不同操作系统版本间文本权限处理方式不同的问题。

所有这些都会导致在开发人员将自己的代码部署到线上时,却无法正常运行。那么是否应将生产环境进行配置来与开发者的电脑相匹配呢,或者是让开发人员在与生产环境相一致的工作环境下进行开发呢?

在理想的世界中,从开发人员的电脑到生产服务器所有内容都应保持一致,但这一乌托邦通过传统的技术难以实现。每个人都有自己的工作习惯和个人喜好,哪怕只有一个系统工程师在开发时强制跨平台的一致性已经很困难了,不消说一个工程师团队与数百个开发人员合作的情况了。

Docker 解决方案

在Mac或Windows上使用Docker,开发人员可以很轻易地将代码封装到他们自定义的容器里,或者在与系统管理员或运维团队合作时将其创建为一个Dockerfile。我们将在第二章 创建容器镜像中讲解这一内容, 并且在第五章 Docker Compose中会深入讲解Docker Compose文件。

开发人员仍然可以选择自己喜欢的IDE,并在开发代码时保持原有的工作流。我们在本章的后续部分中会发现,安装和使用Docker一点都不困难,其实考虑到曾经维护环境一致性的繁琐,哪怕是有自动化的加持,Docker会简单到难以置信 – 像梦一样。

运维人员

作者在从事的多年运维工作中,常常会遇到下面的问题。

问题

假设我们有五台服务器:三台负载均衡web服务器,两台配置为主从用于运行应用一的数据库服务器。我们使用工具Puppet或Chef来自动管理软件栈和5台服务器上的配置。

一切都很顺利,直到接到新的需求。我们需要将应用二部署在运行应用一相同的服务器上。表面上没有任何问题,我们可以修改Puppet或Chef的配置来添加新用户、vhosts、拉取新代码,诸如此类。但是,我们注意到应用二要求使用比应用一更高的软件版本。

如果事情再糟糕一些,我们已知应用一竭力避免与新的软件栈进行兼容,而应用二又不向后兼容。

使用传统技术,我们只有几个选择,每一种都会在某种程度上带来问题:

  1. 请求更多的服务器?这对传统技术可能最安全的技术方案,但并不意味着会有预算来添置更多的资源。
  2. 重新架构方案?从负载均衡或副本中拿出一台web服务器和数据库服务器,以应用二的软件栈重新进行部署,在技术上可能是最简单的方案。但是我们引入了应用二的单点问题,同时也降低了应用二的冗余:我们一开始使用3台web服务器和2台数据库服务器可能是有原因的。
  3. 尝试在我们的服务器上同时安装新的软件?嗯,这肯定会带来问题,刚开始运行项目时这看起来是一个很好的短期方案,但这等于我们手上的是纸牌屋,在随后任意软件栈需要严重安全补丁时会摧枯拉朽般崩溃。

Docker 解决方案

这正是Docker的领域。如果把应用一放在三台服务器的容器中运行,实际可以运行不止三个容器,双倍的容器我们就可以运行6个容器,让我们可以在不降低应用一的可用性的同时部署我们的应用。

在这个环境部署应用二仅仅需要在3台主机上启动容器并使用负载均衡路由到新部署的应用上。因为我们只是在容器中部署,无需担心在同一台服务器上部署、配置和管理不同版本的软件栈。

我们会在第五章 Docker Compose中操作一个具体的实例。

企业

企业也深受前述相同问题的困扰,因为它们通常都会有开发人员和运维人员,但它们的规模更大,因此具有更大的风险。

问题

因为前面所说的风险,以及宕机所带来的销售或声誉的损失,企业需要在发布前对每个部署进行测试。这表示发生如下情况时新功能和修复都会裹足不前:

这一过程可能要花费几天到数周乃至数月的时间,取决于应用的复杂性以及引入变更存在的风险。虽然在技术层面这一过程要确保持续性和可用性,在商业层面这是在引入潜在的风险。如果这一新功能在过程中受阻,而竞争对手提前出了一个相似的功能,或者更糟的是一个相同的功能?

这一情形对销售和声誉带来的损伤和我们一开始所竭力避免的宕机是一样的。

Docker 解决方案

首先要说Docker并不会移除上面我们所描述的操作流程。但是我们也说了,它会让已经连贯运作的事情更为简单。这表示我们的开发们可以在与生产环境相同配置的容器中进行运行。也意味着应用测试的方法不会太过繁杂。

比如,在开发人员查看代码时,他们知道代码可以在本地开发环境上运行(因为这正是他们进行开发的环境),我们的测试工具可以启动相同的容器来进行自动化测试。一旦使用过容器,可以删除来释放资源进行下面的测试。这意味着突然间我们的测试流程和进程变得更加灵活,并且我们可以继续利用相同的环境,而不是为下一套测试重新部署重新制作服务器镜像。

这一流程甚至可推广至将新应用容器直接推到生产环境中。

这一过程完成的越快,我们就越能无后顾之忧地快速上线新功能并引领潮流。

独立主机、虚拟机和Docker之间的区别

那么,我们知道了Docker所能解决的问题。下面需要讨论的是Docker到底是什么以及它能做些什么。

Docker是一个容器管理系统,帮助我们以轻松和统一的方式管理Linux容器(LXC)。这让我们可以在笔记本上的虚拟环境中创建镜像并对其运行命令。在本地电脑上运行这些环境中对容器所执行的操作,和在生产环境中运行相同命令或操作的效果是一样的。

这有助于我们在迁移到生产环境时无需进行额外的操作,比如从本机将应用上线到生产环境服务器。下面我们来看下Docker容器和典型的虚拟主机环境有哪些区别。

下图展示了独立物理主机和运行虚拟主机的服务器之间的区别:

可以看出,对于独立主机我们的三个应用同时共享相同的橙色的软件栈。在虚拟主机上运行三个应用,则可以使用两个完全不同的软件栈。下图显示了使用Docker运行相同的橙色和绿色应用:

这张图中让我们清晰地看到使用Docker的关键好处,即,无需在每次启动容器时创建一个完整的操作系统,这缩减了容器占用的总空间。因为所有的Linux版本都使用标准内核模型,Docker依赖于宿主机操作系统如Red Hat, CentOS和Ubuntu的Linux内核。

因此,我们几乎可以将所有的Linux操作系统作为宿主机操作系统,并可对主机上其它基于Linux的操作系统进行分层 。也就是对于应用来说是安装了完整的操作系统,而现实是我们仅安装了二进制文件,如包管理器、Apache/PHP以及操作系统运行应用所需要的一些其它库。

例如,在前面的图中,我们可以用Red Hat运行橙色应用,Debian运行绿色应用,但绝不需要在主机上实际安装Red Hat 或Debian。因此,Docker的另一个好处是它所创建的镜像的大小。在创建时无需那些大块文件:内核或操作系统。这让镜像很小很紧凑,易于迁移。

安装Docker

首先我们需要的是安装器(Installer),在本地机器和服务器环境中运行Docker。下面来看哪些环境中可以安装Docker:

此外我们可以在公有云中运行Docker,如 AWS(Amazon Web Services)、Microsoft Azure和DigitalOcean,这只是很少一部分。通过前面列出的不同类型的安装器,Docker在操作系统上运行的方式其实并不相同。例如,Docker在Linux上原生运行,所以如使用的是Linux,在系统中运行Docker直截了当。而如果使用的是macOS或Windows 10,运行方式则有些许不同,因为它需要依赖于Linux。

下面分别来看在 Ubuntu 18.04 Linux桌面、macOS和Windows 10上快速安装Docker。

在Linux (Ubuntu 18.04)上安装Docker

前面已经提到,这是三种系统中安装最为直接的一种。要安装Docker,仅需在Terminal中运行如下命令:

安装中会要求将当前用户加到Docker用户组中。要实现添加,运行如下命令即可,要记得将用户名替换成你自己的哦:

这下命令会自行下载、安装并配置最新版的Docker。在写本书时,通过官方安装脚本在Linux操作系统上安装的版本为18.06。

运行如下命令来确认Docker是否安装并运行:

你应该会看到类似如下的输出:

有两个工具将在后续章节中使用到,在macOS和Windows 10安装器中都会作为Docker的一部分进行安装。

要确保在后面的章节中有这些工具可以使用,现在我们应进行安装。第一个工具是Docker Machine。要安装它,首先我们应获取到最新的版本号。可能过访问GitHub页面https://github.com/docker/machine/releases/的版本部分来进行查看。在写本书时,最新版本为0.15.0,读者在安装时可将如下代码块中的版本号在命令中以最新的版本号来进行替换:

要下载并安装接下来这个工具Docker Compose,需要运行下面的命令,同样请在发行版本页面https://github.com/docker/compose/releases查看运行时的最新版本:

一旦完成了安装,我们可以运行如下两个命令来确定相关版本的软件进行了正确安装:

译者注:Alan 在译本章时最新版本分别为v0.16.1和1.24.0-rc3

在macOS上安装Docker

和Linux上的命令行安装不同,Docker在Mac上有一个图形化安装程序。

ℹ️在进行下载前,确保所运行的系统为Apple macOS Yosemite 10.10.3 或以上的版本。如果你运行的是更老的版本,不必担心,还是可以安装的,参照本章“更老的操作系统”一节。

我们可以从Docker商店上下载安装程序,地址为:点击这里。仅需点击Get Docker这一链接,即可下载DMG安装包。双击安装包就会挂载镜像,桌面上打开的挂载镜像如下图所示:

译者注:不想注册的朋友可直接访问下载链接:点击这里

在将Docker图标拖拽到Applications文件夹中之后,双击图标就会提示你是否要打开所下载的程序。点击Yes会打开Docker安装程序,如下所示:

译者注:Alan 并非初次安装,所以并未见到此页面及下面的页面

点击Next并遵循屏幕上的指令。在安装和启动后,我们就可以在屏幕上方的图标栏中看到Docker的图标。点击图标并选择About Docker Desktop将会出现类似下面的页面:

也可以打开Terminal窗口。像在Linux安装中那样运行如下命令:

你应该可以看到类似如下的Terminal输出:

也可以运行如下命令来查看与Docker Engine一起安装的Docker Compose和Docker Machine的版本:

在Windows 10专业版上安装Docker

和在Mac上安装Docker一样,Windows上安装Docker也使用图形化安装程序。

ℹ️在下载前,确保运行的为Microsoft Windows 10专业版或企业版64位系统。如果运行的是更老的版本或者Windows 10的其它版本,还是可以运行Docker的,参照本章“更老操作系统”一节了解更多信息。

Windows上的Docker有这一要求,是出于对Hyper-V的依赖。Hyper-V是Windows的原生虚拟机,允许在Windows上运行x86-64客户端,系统可以为Windows 10专业版或Windows服务器版。它甚至形成了Xbox One操作系统的一部分。

可以在Docker商店中下载Windows版的Docker安装程序,地址为点击这里。下载后,运行MSI包,就会看到如下的欢迎信息:

译者注:不想注册的朋友可直接访问下载链接:点击这里。Alan 安装时并未发现有欢迎界面,以上是安装过程中的页面

点击Yes并遵循屏幕上的提示,不仅会安装Docker,如未启动Hyper-V的话还会启动Hyper-V。

在安装完成后,就可以看到屏幕右下角图标托盘中有一个Docker图标。点击图标并选择菜单中的About Docker会显示如下内容:

打开PowerShell窗口并输入如下命令:

会显示与Mac和Linux版本相似的输出:

同样,我们还可以运行如下命令来查看与Docker Engine同时安装了的Docker Compose和Docker Machine的版本:

同样会看到与macOS和Linux版本上相似的输出。你可能已经总结出,在完成包的安装后,使用上会极其相似。这些将在本章稍后详细说明。

补充

1 出现cannot enable hyper-v service报错时请在bios中开启虚拟化配置

2 Error response from daemon: open \\.\pipe\docker_engine_linux: The system ca…

更老的操作系统

如果所运行的Mac或Windows操作系统不够新,未满足要求,那么你需要使用Docker Toolbox。思考下运行如下命令所打印的输出:

在至此我们所安装的三个版本中,都会显示两个版本号:客户端和服务端。可以预测到,Linux版本中显示的客户端和服务端架构均为Linux,但在Mac版本中显示客户端运行在Darwin上,这是Apple的类Unix内核,在Windows上显示的版本为Windows。但两者的服务端的架构均显示为Linux,这是怎么回事呢?

这是因为Mac和Windows的Docker安装版本都在后台运行了虚拟机,而这一虚拟机运行了一个小型、轻量的基于Alpine Linux的操作系统。虚拟机使用Docker自身库运行,与所使用的环境内置的Hypervisor进行连接。

macOS 中内置的为Hypervisor.framework,Windows中为Hyper-V。

为确保所有人都能体验Docker,Docker有一个不使用内置hypervisor的版本,可在老版本的macOS以及未支持的Windows版本中使用。这些版本利用VirtualBox来作为hypervisor来运行Linux服务端,供客户端连接。

ℹ️VirtualBox是一个由Oracle开发的开源x86和AMD64/Intel64虚拟化产品。可运行于Windows、Linux、Macintosh和Solaris主机上,支持许多Linux、Unix和Windows客户操作系统。更多有关VirtualBox的知识,请访问https://www.virtualbox.org/。

更多有关Docker Toolbox的知识,参见项目网站,在这里可以下载macOS和Windows的安装程序。

小贴士:本书假定读者已在Linux上安装了最新版Docker,或使用Mac或Windows上的Docker。虽然使用Docker Toolbox安装的Docker应该可以运行本书的命令,但读者可能会遇到一些文件权限以及从本机向容器挂载数据的所有权的问题。

Docker命令行客户端

既然已经安装了Docker,我们就来看你可能已经熟悉了的一些Docker命令。我们会以一些常用命令开始,然后来看一些用于Docker镜像的命令。接着将深入用于容器的命令。

小贴士:Docker重构了命令行客户端来对命令进行更符合逻辑的分组,这时因为客户端提供的功能数量在快速增长,并且命令存在交叉重叠的情况。在本书中我们将使用这一新的结构。

我们要来看的第一个命令是最有用的命令之一,不仅是在Docker中,我们使用的任何命令行工具都是这样:help命令。仅需如下这样运行:

这一命令会列出所有可用的Docker命令,并伴有一个简短的描述说明每个命令的功能。想要获取指定命令的帮助信息,可以运行如下命令:

下一步,我们来运行hello-world容器。仅需通过运行如下命令来实现:

不用担心Docker所运行的主机,在Linux, macOS和Windows上发生的情况是一样的。Docker会下载hello-world容器镜像,然后执行,在执行后,就会停止容器。

Terminal会话中的结果类似这样:

让们来做进一步的探索:通过运行如下两条命令下载并运行一个Nginx容器:

第一条命令下载Nginx容器镜像,第二条命令在后台启动容器,名为nginx-test,使用的是我们所拉取的Nginx镜像。同时还将容器的端口80与宿主机上的8080端口进行了映射,这样在本地浏览器中通过http://localhost:8080/即可访问。

可以从如下截图中看出,该命令运行的结果在三种操作系统中都是一样的。以下是 Linux 中的结果:

以下是macOS上的运行结果:

以下是 Windows 上的运行结果:

在接下来的三章中,我们会来深入地学习Docker命令行客户端的使用。这里我们先运行如下命令停止并删除我们的nginx-test容器:

可以看到,运行简单的Nginx容器在安装了Docker的三个主机上的体验是完全一致的。 相信你也能想象到,如果不使用Docker想要在三种平台上实现这样的效果是非常具有挑战性的,在每个平台上的体验也会不同。这也是曾经本地开发环境所产生不同的原因。

Docker和容器生态

如果你一直在追随Docker和容器的发展的话,会注意到最近几年Docker网站上发布的消息开始有所变化,头条由什么是容器转为更多聚焦在Docker作为一家公司提供什么服务。

这其中的一个核心驱动是曾经所有的东西都被堆砌在一起并称之为Docker,这会带来困惑。既然现在人们已经无需再接受什么是容器以及Docker能解决什么问题的教育,该公司需要抓紧与市面上雨后春笋般的提供各类容器技术的其它公司进行区分。

下面我们就来尝试拆解Docker,包含如下内容:

我们还会在本章后面看一些其它第三方服务。同时,我们来详细了解以上这些,先从开源项目开始。

开源项目

Docker, Inc.用过去的两年开源并向多个开源基金会和社区捐赠了很多核心项目。包含如下这些项目:

我们可能永远不会独立地使用单个的组件,但是,所提到的每个项目都是由Docker, Inc维护的工具的组件。我们会在最后一章中更深入地了解这些项目。

Docker CE和Docker EE

有很多Docker, Inc提供和支持的工具。有些前面已经提到,另一些将会在后续章节中讲到。在结束第一章之前,我们应有一个将要使用的工具的概念。其中最重要的就是内核Docker Engine。

这是Docker的核心,我们讲解的所有其它工具都会使用它。我们已使用了Docker引擎,因为在安装Docker时已对其进行了安装以及在本章Docker命令一节进行了使用。目前有两个版本的Docker引擎,Docker企业版(EE)和Docker社区版(CE)。本书将使用的是Docker CE。

从2018年9月起,Docker CE的稳定版发布周期为一年两次,也就是说有7个月的维护周期。这表示你有足够的时间审查并为升级做准备。在写本书时,当前Docker CE发行版的时间表为:

在发布Docker CE稳定版本的同时,Docker会通过nightly仓库(此前的Docker CE Edge)提供Docker Engine的nightly构建版本,同时通过Edge渠道按月发布Mac及Windows版的Docker。

Docker还提供如下工具和服务:

Docker, Inc.

Docker, Inc.是为开发Docker CE和Docker EE所形成的公司。它还为Docker EE提供基于SLA的支持服务,向想要对已有应用容器化并加入MTA(Modernize Traditional Apps)项目的公司提供咨询服务。

总结

本章中,我们讲解了一些可能在学习本章前你已经知道(至少现在知道)的知识。我们首先学习了什么是Docker的基础知识,以及相对其它主机类型有什么好处。我们讲解了安装程序,在不同操作系统中的运行方式,以及如何通过命令行来进行控制。一定要记得查看安装程序的要求,来确保你使用对应操作系统的正确安装程序。

然后我们深入到Docker的使用,并讲解了一些开始使用的基本命令。我们会在未来的章节中来学习所有的管理命令,深入理解这些命令以及如何、何时使用这些命令。最后,我们讨论了Docker生态系统以及不同工具各自承担的职责。

下一章中,我们会来学习如何构建基容器,并深入学习Dockerfile和存储镜像的位置,以及使用环境变量和Docker数据卷。

课后问题

  1. 在哪里可以下载Mac和Windows的Docker安装包?
  2. 使用什么命令来下载 Nginx 镜像?
  3. 哪一个开源项目是核心Docker Engine的上游项目?
  4. 稳定版Docker CE支持的生命周期是几个月?
  5. 运行哪个命令来查找Docker容器命令子集的更多信息?

 

扩展阅读

本章中我们讨论了如下的hypervisors:

我们参考了Docker的如下博客文章:

接着我们讨论了如下开源项目:

最后,在本章开始处所讨论的迷因可在这里查看:

退出移动版