Docker 是一个容器化平台,它包装你所有开发环境依赖成一个整体,像一个容
器。保证项目开发,如开发、测试、发布等各生产环节都可以无缝工作在不同
的平台
Docker 容器:将一个软件包装在一个完整的文件系统中,该文件系统包含运行
所需的一切:代码,运行时,系统工具,系统库等。可以安装在服务器上的任
何东西。
这保证软件总是运行在相同的运行环境,无需考虑基础环境配置的改变。
Docker 技术有三中主要的技术途径辅助完成此需求:
存储卷(Volumes)
环境变量(Environment variable)注入
只读(Read-only)文件系统
虽然 ADD 和 COPY 功能相似,推荐 COPY 。
那是因为 COPY 比 ADD 更直观易懂。 COPY 只是将本地文件拷入容器这么简
单,而 ADD 有一些其它特性功能(诸如,本地归档解压和支持远程网址访问
等),这些特性在指令本身体现并不明显。因此,有必要使用 ADD 指令的最好
例子是需要在本地自动解压归档文件到容器中的情况,如 ADD
rootfs.tar.xz 。
Docker image 是 Docker 容器的源。换言之,Docker images 用于创建
Docker 容器(containers)。映像(Images)通过 Docker build 命令创建,
当 run 映像时,它启动成一个 容器(container)进程。 做好的映像由于可
能非常庞大,常注册存储在诸如 registry.hub.docker.com 这样的公共平台
上。映像常被分层设计,每层可单独成为一个小映像,由多层小映像再构成大
映像,这样碎片化的设计为了使映像在互联网上共享时,最小化传输数据需
求。
Docker containers -- Docker 容器 -- 是包含其所有运行依赖环境,但与其
它容器共享操作系统内核的应用,它运行在独立的主机操作系统用户空间进程
中。Docker 容器并不紧密依赖特定的基础平台:可运行在任何配置的计算机,
任何平台以及任何云平台上。
Docker hub 是云基础的 Docker 注册服务平台,它允许用户进行访问 Docker
中心资源库,创建自己的 Docker 映像并测试,推送并存储创建好的 Docker
映像,连接 Docker 云平台将已创建好的指定 Docker 映像布署到本地主机等
任务。它提供了一个查找发现 Docker 映像,发布 Docker 映像及控制变化升
级的资源中心,成为用户组或团队协作开发中保证自动化开发流程的有效技术
途径。
段?
在任意时间点,一个 Docker 容器可能存在以下运行阶段:
运行中(Running)
已暂停(Paused)
重启中(Restarting)
已退出(Exited)
使用如下命令行命令确定一个 Docker 容器的运行状态
$ docker ps –a
这将列表形式输出运行在主机上的所有 Docker 容器及其运行状态。从这个列
表中很容易找到想要的容器及其运行状态。
一些最常用的指令如下:
FROM:使用 FROM 为后续的指令建立基础映像。在所有有效的 Dockerfile
中, FROM 是第一条指令。
LABEL:LABEL 指令用于组织项目映像,模块,许可等。在自动化布署方面
LABEL 也有很大用途。在 LABEL 中指定一组键值对,可用于程序化配置或布署
Docker 。
RUN:RUN 指令可在映像当前层执行任何命令并创建一个新层,用于在映像层中
添加功能层,也许未来的层会依赖它。
CMD:使用 CMD 指令为执行的容器提供默认值。在 Dockerfile 文件中,若添
加多个 CMD 指令,只有最后的 CMD 指令运行。
器技术?
对于 Docker 容器创建无状态性(Stateless)的应用更可取。通过从应用项目
中将与状态相关的信息及配置提取掉,我们可以在项目环境外建立不依赖项目
环境的 Docker 容器。这样,我们可以在任意产品中运行同一容器,只需根据
产品需要像问 & 答(QA)一样给其配置环境即可。 这帮助我们在不同场景重
用相同的 Docker 映像。另外,使用 无状态性(Stateless)容器应用相比有
状态性(Stateful)容器应用更具伸缩性,也容易创建。
初始,所有都有赖于 Dockerfile 配置文件。Dockerfile 配置文件就是创建
Docker image (映像) 的源代码。
48
一旦 Dockerfile 配置好了,就可以创建(build)并生成 'image(映像)
' ,'image' 就是 Dockerfile 配置文件中 「源代码」的「编译」版本。
一旦有了 'image' ,就可以在 registry(注册中心) 发布它。 'registry'
类似 git 的资源库 -- 你可以推送你的映像(image),也可取回库中的映像
(image)。
之后,你就可以使用 image 去启动运行 'containers(容器)'。运行中的容
器在许多方面,与虚拟机非常相似,但容器的运行不需要虚拟管理软件的运
行。
Image:一个 Docker Image 是由一系列 Docker 只读层(read-only Layer)
创建出来的。
Layer:在 Dockerfile 配置文件中完成的一条配置指令,即表示一个 Docker
层(Layer)。
如下 Dockerfile 文件包含 4 条指令,每条指令创建一个层(Layer)。
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
重点,每层只对其前一层进行一(某)些进化。
最初的构想,virtualisation(虚拟化) 被认为是逻辑划分大型主机使得多个
应用可以并行运行的一种技术方案。然而,随着技术公司及开源社区的推进,
现实发生了戏剧性的转变,以致产生了以一种或某种方式操作特权指令可以在
单台基于 x86 硬件的系统上同时运行多个(种)操作系统的技术。
实质的效果是,虚拟化技术允许你在一个硬件平台下运行 2 个完全不同的操作
系统。每个客户操作系统可完成像系统自检、启动、载入系统内核等像在独立
硬件上的一切动作。同时也具备坚实的安全基础,例如,客户操作系统不能获
取完全访问主机或其它客户系统的权限,及其它涉及安全,可能把系统搞坏的
操作。
基于对客户操作系统虚拟硬件、运行环境模拟方法的不同,对虚拟化技术进行
分类,主要的有如下 3 种虚拟化技术种类:
? 全模拟(Emulation)
? 半虚拟(Paravirtualization)
? 基于容器的虚拟化(Container-based virtualization)
hypervisor -- 虚拟管理层(程序)-- 负责创建客户虚拟机系统运行所需虚拟
硬件环境。它监管客户虚拟操作系统的运行,并为客户系统提供必要的运行资
源,保证客户虚拟系统的运行。虚拟管理层(程序)驻留在物理主机系统和虚
拟客户系统之间,为虚拟客户系统提供必要的虚拟服务。如何理解它,它侦听
运行在虚拟机中的客户操作系统的操作并在主机操作系统中模拟客户操作系统
所需硬件资源请求。满足客户机的运行需求。
50
虚拟化技术的快速发展,主要在云平台,由于在虚拟管理程序的帮助下,可允
许在单台物理服务器上生成多个虚拟服务器,驱动着虚拟化技术快速发展及广
泛应用。诸如,Xen,VMware,KVM 等,以及商业化的处理器硬件生产厂商也加
入在硬件层面支持虚拟化技术的支持。诸如,Intel 的 VT 和 AMD-V 。
Docker Swarm -- Docker 群 -- 是原生的 Docker 集群服务工具。它将一群
Docker 主机集成为单一一个虚拟 Docker 主机。利用一个 Docker 守护进程,
通过标准的 Docker API 和任何完善的通讯工具,Docker Swarm 提供透明地将
Docker 主机扩散到多台主机上的服务。
Docker 在产品中提供如 运行统计和 Docker 事件的工具。可以通过这些工具
命令获取 Docker 运行状况的统计信息或报告。
Docker stats : 通过指定的容器 id 获取其运行统计信息,可获得容器对
CPU,内存使用情况等的统计信息,类似 Linux 系统中的 top 命令。
Docker events :Docker 事件是一个命令,用于观察显示运行中的 Docker 一
系列的行为活动。
一般的 Docker 事件有:attach(关联),commit(提交),die(僵死),
detach(取消关联),rename(改名),destory(销毁)等。也可使用多个选
项对事件记录筛选找到想要的事件信息。
孤儿卷是未与任何容器关联的卷。在 Docker v。1.9 之前的版本中,删除这些
孤儿卷存在很大问题。
Paravirtualization,也称为第 1 类虚拟机管理(层)程序,其直接在硬件或
裸机(bare-metal)上运行,提供虚拟机直接使用物理硬件的服务,它帮助主
机操作系统,虚拟化硬件和实际硬件进行协作以实现最佳性能。这种虚拟层管
理技术的程序一般占用系统资源较小,其本身并不需要占用大量系统资源。
22、Docker 技术与虚拟机技术有何不同?
Docker 不是严格意义上的虚拟化硬件的技术。它依赖 container-based
virtualization(基于容器的虚拟化) 的技术实现工具,或可以认为它是操作
系统用户运行级别的虚拟化。因此, Docker 最初使用 LXC 驱动它,后来移至
由 libcontainer 基础库驱动它,现已更名为 runc 。 Docker 主要致力于应
用容器内的应用程序的自动化部署。应用容器设计用于包装和运行单一服务,
而操作系统设计用于运行多进程任务,提供多种运算服务的能力。如虚拟机中
等同完全操作系统的能力。因此,Docker 被认为是容器化系统上管理容器及应
用容器化的布署工具。
与虚拟机不同,容器无需启动操作系统内核,因此,容器可在不到 1 秒钟
时间内运行起来。这个特性,使得容器化技术比其它虚拟化技术更具有独
特性及可取性。
? 由于容器化技术很少或几乎不给主机系统增加负载,因此,基于容器的虚
拟化技术具有近乎原生的性能表现。
? 基于容器的虚拟化,与其他硬件虚拟化不同,运行时不需要其他额外的虚
拟管理层软件。
? 主机上的所有容器共享主机操作系统上的进程调度,从而节省了额外的资
源的需求。
? 与虚拟机 image 相比,容器(Docker 或 LXC images)映像较小, 因
此,容器映像易于分发。
? 容器中的资源分配由 Cgroups 实现。 Cgroup 不会让容器占用比给它们分
配的更多的资源。但是,现在其它的虚拟化技术,对于虚拟机,主机的所
有资源都可见,但无法使用。这可以通过在容器和主机上同时运行 top 或
htop 来观察到。在两个环境中的输出看起来相同。
23、请解释一下 docerfile 配置文件中的 ONBUILD 指令的用途
含义?
配置文件中的 ONBUILD 指令为创建的 Docker image (映像)加入在将来执行
的指令(译注:在当前配置文件生成的映像中并不执行), 用于在以这个创建
的映像为基础的创建的子映像(image) 中执行或定制。 举例, 以基映像创
建自己的映像时,可定制创建特有的用户化的配置环境。
( 译注: 由于原文较短,关于这个问题容易迷惑。 译者认为,总体来说关键
理解 -- 以基础映像创建自有的映像过程中,基础映像中所有的创建层或指令
是以整体或固化的方式导入自有映像中的,自有映像是不能对这个过程进行自
有定制。 而 ONBUILD 指令提供了将某些层从基础映像中剥离出来提供给之后
以自有映像为基础映像派生新的映像的可定制途径。这对发布映像而普适在不
同的运行环境定制非常有用。不当之处,请指正!)
24、有否在创建有状态性的 Docker 应用的较好实践? 最适合的
场景有什么?
有状态性 Docker 应用的问题关键在于状态数据保存在哪儿的问题。 若所有数
据保存在容器内, 当更新软件版本或想将 Docker 容器移到其它机器上时,
找回这些在运行中产生的状态数据将非常困难。
您需要做的是将这些表达运行状态的数据保存在永久卷中。参考如下 3 种模
式。
译注:
1 图中文字: 数据保存在容器中,当容器停止运行时,运行状态数据丢失!
2 图中文字: 数据保存在主机卷(Host Volume)中,当主机停机时,运行状
态数据将无法访问
3 图中文字: 数据保存在网络文件系统卷中,数据访问不依赖容器的运行与主
机的运行
若您使用:docker run -v hostFolder:/containerfolder 命令运行您的容
器, 容器运行中任何对 /containerfolder 目录下数据的改变, 将永久保存
在主机的 hostfolder 目录下。 使用网络文件系统(nfs)与此类似。 那样您
就可以运行您的容器在任何主机上且其运行状态数据被保存在网络文件系统
上。
25、在 Windows 系统上可以运行原生的 Docker 容器吗?
在 'Windows Server 2016' 系统上, 你可以运行 Windows 的原生容器, 微
软推出其映像是 'Windows Nano Server' , 一个轻量级的运行在容器中的
Windows 原生系统。 您可以在其中布署基于 .NET 的应用。
译注: 结合 Docker 的基本技术原理,参考后面的 问题 26 和 问题 27, 可
推测, 微软在系统内核上开发了对 Docker 的支持, 支持其闭源系统的容器
化虚拟技术。但译者认为, Windows 系统本就是闭源紧耦合的系统, 好像你
在本机上不装 .NET 组件,各应用能很好运行似的。何必再弄个容器,浪费资
源。这只是译者自己之孔见,想喷就喷! 另: Windows Server 2016 版本之
后的都可支持这种原生 Docker 技术,如 Windows Server 2018 版。
26、在非 Linux 操作系统平台上如何运行 Docker ?
容器化虚拟技术概念可能来源于,在 Linux 内核版本 2.6.24 上加入的对 命
名空间( namespace) 的技术支持特性。 容器化进程加入其进程 ID 到其创
建的每个进程上并且对每个进程中的系统级调用进行访问控制及审查。 其本身
是由系统级调用 clone () 克隆出来的进程, 允许其创建属于自己命名空间的
进程实例,而区别于之前的,归属与整个本机系统的进程实例。
如果上述在 Linux 系统内核上的技术实现成为可能, 那么明显的问题是如何
在 非 Linux 系统上运行容器化的 Docker 。过去, Mac 和 Windows 系统上
运行 Docker 容器都使用 Linux 虚拟机(VMs) 技术, Docker 工具箱使用的
容器运行在 Virtual Box 虚拟机上。 现在,最新的情况是, Windows 平台上
使用的是 Hyper-V 产品技术,Mac 平台上使用的是 Hypervisor.framework
(框架)产品技术。
27、容器化技术在底层的运行原理?
2006 年前后, 人们,包括一些谷歌的雇员, 在 Linux 内核级别上实现了一
种新的名为 命名空间(namespace) 的技术(实际上这种概念在 FreeBSD 系
统上由来已久)。我们知道,操作系统的一个功能就是进程共享公共资源, 诸
如,网络和硬盘空间等。 但是,如果一些公共资源被包装在一个命名空间中,
只允许属于这个命名空间中的进程访问又如何呢? 也就是说,可以分配一大块
硬盘空间给命名空间 X 供其使用,但是,命名空间 Y 中的进程无法看到或访
问这部分资源。 同样地, 命名空间 Y 中分配的资源,命名空间 X 中的进程
也无法访问。当然, X 中的进程无法与 Y 中的进程进行交互。这提供了某种
对公共资源的虚拟化和隔离的技术。
这就是 Docker 技术的底层工作原理: 每个容器运行在它自己的命名空间中,
但是,确实与其它运行中的容器共用相同的系统内核。 隔离的产生是由于系统
内核清楚地知道命名空间及其中的进程,且这些进程调用系统 API 时,内核保
证进程只能访问属于其命名空间中的资源。
图上文字说明: 运行中的容器是隔离的。准确地说, 各容器共享操作系统内
核及操作系统 API。
28、说说容器化技术与虚拟化技术的优缺点
仅有下面的一些对比:
不能像虚拟机那样在容器上运行与主机完全不同的操作系统。 然而, 可以在
容器上运行不同的 Linux 发布版,由于容器共享系统内核的缘故。容器的隔离
性没有虚拟机那么健壮。事实上, 在早期容器化技术实现上,存在某种方法使
客户容器可接管整个主机系统。
也可看到,载入新容器并运行,并不会像虚拟机那样装载一个新的操作系统进
来。
所有的容器共享同一系统内核, 这也就是容器被认为非常轻量化的原因。
同样的原因,不像虚拟机, 你不须为容器预分配大量的内存空间, 因为它不
是运行新的整个的操作系统。 这使得在一个操作系统主机上,可以同时运行成
百上千个容器应用, 在运行完整操作系统的虚拟机上,进行这么多的并行沙箱
实验是不可能的。
29、如何使 Docker 适应多种运行环境?
您必然想改变您的 Docker 应用配置以更适应现实运行环境的变化。下面包含
一些修改建议:
移除应用代码中对任何固定存储卷的绑定,由于代码驻留在容器内部,而不能
从外部进行修正。
绑定应用端口到主机上的不同端口
差异化设置环境变量 (例如: 减少日志冗余或者使能发电子邮件)
设定重启策略(例如: restart: always ), 避免长时间宕机
加入额外的服务(例如: log aggregator)
由于以上原因, 您更需要一个 Compose 配置文件,大概叫
production.yml ,它配置了恰当的产品整合服务。 这个配置文件只需包含您
选择的合适的原始 Compose 配置文件中,你改动的部分。
docker-compose -f docker-com
30、为什么 Docker compose 采取的是并不等待前面依赖服务项
的容器启动就绪后再启动的组合容器启动策略?
Docker 的 Compose 配置总是以依赖启动序列来启动或停止 Compose 中的服务
容器, 依赖启动序列是由 Compose 配置文件中的 depends_on , links ,
volumes_from 和 network_mode: "service : ..." 等这些配置指令所确定
的。
然而, Compose 启动中, 各容器的启动并不等待其依赖容器(这必定是你整
个应用中的某个依赖的服务或应用)启动就绪后才启动。使用这种策略较好的
理由如下:
等待一个数据库服务(举例)就绪这样的问题, 在大型分布式系统中仅是相比
其它大问题的某些小问题。 在实际发布产品运维中, 您的数据库服务会由于
各种原因,或者迁移宿主机导致其不可访问。 您发布的产品需要有应对这样状
况的弹性。
掌控这些, 开发设计您的应用, 使其在访问数据库失效的情况下, 能够试图
重连数据库, 直至其连接到数据库为止。
最佳的解决方案是在您的应用代码中检查是否有应对意外的发生,无论是任何
原因导致的启动或连接失效都应考虑在内。