凌云的博客

行胜于言

理解 Docker

分类:other| 发布时间:2014-06-21 23:32:57


什么是 Docker ?

Docker 是一个用于开发,传输(shipping)和运行应用的开放平台。 Docker 是设计来更快的分发你的应用的。 通过 Docker 你可以将你的应用从基础设施中分离,并且将你的基础设施看作是一个可管理的应用。 Docker 可以帮助你更快地传输代码,更快地测试,更快地部署,以及缩短编写代码和运行代码的周期。

Docker 通过合并一个轻量级的虚拟化容器和一系列帮助你管理和部署应用的工具来实现这些。

所有这些的核心是 Docker 提供了一个几乎可以将任何程序运行在一个隔离的安全的容器中的方法。 隔离性和安全性允许你同时允许多个容器。而容器天生的轻量级特性(不需要太多额外的资源), 则意味着你可以更大化的榨取你的硬件。

围绕着容器的虚拟化工具和平台可以在以下几个方面帮助你:

  • 将你的应用(和支持组件)放进 Docker 容器中
  • 将这些容器发布和分发给你的团队用于开发和测试
  • 将这些程序部署到你的生产环境(可以是本地数据中心或者云端)

我可以用 Docker 来做什么 ?

更快地分发你的应用

Docker 很适合在开发周期为你提供帮助。 Docker 允许你的开发者在本地的容器中进行应用和服务的开发。 它可以集成到持续集成和部署工作流。

比如:你的开发者在本地进行代码的开发然后通过 Docker 分享他的开发栈给他的同事。 当一切就绪,他们可以将他们的开发代码和栈推送到测试环境以及执行任何需要的测试。 然后你可以将测试环境中的 Docker images 推送到生产环境并且部署你的代码。

更容易地部署和扩展

Docker 是一个具有高度可移植的工作负载的基于容器的平台。 Docker 容器可以运行在开发者的本地物理机或者数据中心的虚拟机或者云上。

得益于 Docker 的可移植性和轻量级特性,我们可以容易地进行动态的工作负载的管理。 你可以通过 Docker 来快速的扩展和移除你的应用以及服务。 Docker 的快速运行意味着可以接近实时地进行扩展。

实现更高的密度和运行更多的工作负载

Docker 是轻量级以及快速的。 它提供一个可行的,具有成本效益的替代基于管理程序的虚拟机。 这是在高密度环境中尤其有用:比如构建自己的云或平台即服务(Platofrm-as-a-Service)。

Docker的主要组件

Docker 由以下两个主要组件:

  • Docker:开源的容器虚拟平台
  • Docker Hub:用于分享和管理 Docker 容器的软件即服务(Software-as-a-Service)平台

注意:Docker 是基于开发协议:Apache 2.0 license 发布的。

Docker 的架构

Docker 使用 客户-服务 架构。 Docker 客户端和 Docker 守护进程通信,通知 Docker 守护进程进行构建,运行和发布 Docker 容器。 Docker 客户端和 Docker 守护进程可以运行在同一台机器上,Docker 客户端也可以连接到远程的 Docker 守护进程上。 Docker 客户端和服务器通过 sockets 或者 RESTful API 进行通信。

Docker 守护进程

如上图所示,Docker 守护进程运行在 HOST 机上。用户不会直接与守护进程交互,而是通过 Docker 客户端。

Docker 客户端

Docker 客户端是 Docker 的主要用户接口。 它用于接收用户的命令并且和 Docker 守护进程通信。

Docker 内幕

为了理解 Docker 的内幕,你需要知道 Docker 的三个主要组件:

  • Docker images
  • Docker registries
  • Docker 容器
Docker images

Docker image 是一个只读的模板。 比如:一个 image 可以包含一个 安装了 Apache 的 Ubuntu 操作系统。 Images 用于创建 Docker 容器。 Docker 提供了一种简单的方法来创建新的 images 或者更新已有的 images 或者你可以下载那些别人已经创建好的 Docker images。 Docker images 是 Docker 的构建组件。

Docker Registries

Docker registries 保存 iamges。 它们可以保存你可以上传/下载的 公共或者私有的 images。 公共的 Docker registry 称为 Docker Hub。 它提供大量的已有 images 供你使用。 这些 images 可以是你创建的或者其他人之前创建的。 Docker registries 是 Docker 中的 distribution 组件。

Docker 容器

Docker 容器类似于一个目录。 一个 Docker 容器包含了运行应用所需要的所有东西。 每个容器由一个 Docker image 创建。 Docker 容器可以运行,开始,停止,移动和删除。 每个容器是一个隔离和安全的应用平台。 Docker 容器是 Docker 的运行组件。

Docker 如何工作

目前为止,我们已经学习了:

  1. 你可以创建你的 Docker images 来保存你的应用。
  2. 你可以从 Docker images 中创建 Docker 容器来运行你的应用。
  3. 你可以通过 Docker Hub 或者 你自己的 registry 来分享你的 images。

让我们来看看这些元素如何组合起来使 Docker 工作。

Docker Image 如何工作

我们已经知道 Docker images 是一个用于运行 Docker 容器的只读模板。 每个 image 由一系列的层次组成。 Docker 使用 union file system 来将这些层次组合成一个单独的 image。 Union file system 允许独立文件系统中的文件和目录,也就是分支,透明地覆盖,组成一个单一连贯的文件系统。

Docker 这么轻量级的一个原因是这些层级。 当你修改一个 Docker image(比如:更新一个应用的版本),将会创建一个新的层。 因此,比起替换掉整个 image 或者完全rebuild(就像你在虚拟机做的那样),只有那一层添加或者更新。 现在你不需要发布整个新的 image,只需要更新,这可以让发布 Docker images 更快以及更简单。

每个 image 由一个 base image 开始(比如:ubuntu,或者fedora)。 你也可以使用你自己的 images 作为新的 iamge 的 base image。

注意:Docker 经常从 Docker Hub 中获取 base images。
以这些已有的 image 作为 base images,然后使用一系列简单,易懂的指令创建新的 Docker images。 每条指令创建我们的 image 中的一个新的层。

指令包含类似下面的动作:

  • 运行一条命令。
  • 添加一个文件或者目录。
  • 创建一个环境变量。
  • 当这个 image 的容器启动时运行什么进程。

这些指令保存在一个称为 Dockerfile 的文件中。 当你请求构建一个 image 时,Docker 读取这个文件,执行指令,然后返回最终的 image。

Docker registry 如何工作

Docker registry 是你的 Docker images 的存储。 当你构建完一个 Docker image 后,你可以将它 push 到公共的 registry Docker Hub 或者你自己的 registry。

使用 Docker 客户端,你可以搜索那些已经发布的 images 然后你可以拉取它们到你的 Docker host 然后生成容器。

Docker Hub 提供了公共的和私有的 images 存储。 公共的存储是可以由任何人搜索和下载的。而私有存储是只有你自己可以搜索和使用。

容器如何工作

一个容器由操作系统,用户添加的文件和元数据组成。 容器是由 image 创建的。 那个 image 告诉 Docker 容器有什么东西,什么进程在运行以及一系列配置数据。 Docker image 是只读的。 当一个容器运行,它会在 image 上添加一个读写的层。

当你运行一个容器时会发生什么

比如:

$ docker run -i -t ubuntu /bin/bash

让我们分析一下这条命令。

当运行这条命令时 Docker 客户端告诉 Docker 守护进程:

  • 由什么 Docker image 创建容器,在这里是ubuntu
  • 当容器启动时,你希望运行什么程序,在这里是 /bin/bash

当我们运行这条命令后会发生什么呢?

Docker 会按顺序做以下事情:

  • 拉取 ubuntu image:Docker 会检查本地是否已经有这个 image,如果不存在,Docker 会从 Docker Hub下载
  • 创建一个新的容器
  • 创建一个文件系统并且挂载为读写
  • 创建一个 网络/网桥 接口
  • 设置 IP 地址
  • 执行你指定的程序
  • 获取你的程序的输入,输出和出错信息

底层技术

Docker 是用 Go 语言编写的,并且使用了 Linux 内核的特性

命名空间

Docker 的一个优势是使用了命名空间来隔离工作环境(我们称为容器)。 当你运行一个容器时,Docker 为那个容器创建一系列的命名空间。

这提供了一层的隔离:容器中的每一方面都是运行在它自己的命名空间中并且不会访问到外面。

Docker 使用的一些命名空间有:

  • pid 命名空间:用于进程隔离
  • net 命名空间:用于管理网络接口
  • ipc 命名空间:用于管理 IPC 资源
  • mnt 命名空间:用于管理挂在点
  • uts 命名空间:用于隔离内核和版本标识(UTS:Unix Timesharing System)

Control groups

Docker 同时使用了另一项称为 cgroups 或者 control groups 的技术。 在隔离环境中运行程序的一个关键点是它们只使用你想要的资源。 这确保了容器是主机上的良好 multi-tenant citizens。 Control groups 允许 Docker 分享硬件资源给容器,并且,如果需要设置限制和约束。 比如:限制特性容器所使用的最大内存。

Union file systems

Union file systems 或者 UnionFS 是通过创建层次,使得它们非常轻量级和高速。 Docker 使用 union file system 来提供构建容器的块。 Docker 可以使用 union file system 的几种变种,包括:AUFS,btrfs,vfs 和 DeviceMapper。

容器格式

Docker 将这些组件组合成一个包装器(我们称之为 容器格式)。 默认的容器格式称为:libcontainer。 Docker 同时也可以通过使用 LXC 来支持传统的 Linux 容器。 在未来,Docker 或许会支持其他的容器格式,比如整合 BSD Jails 或者 Solaris Zones。

参考

Understanding Docker