Docker的组成:
- Docker Engine,一个轻量级、强大的开源容器虚拟化平台,使用包含了工作流的虚拟化技术,帮助用户建立、并容器化一个应用。
- Docker Hub,提供的一个SaaS服务,用来分享和管理你的程序栈
Docker的优点:
- 应用程序快速交付
- 部署和扩展更加简便
- 更高的部署密度,更满的运行负载
- 更快的部署使得管理更加简单
Docker的架构:
Docker使用CS的架构,包括Docker Client和Docker Daemon两个部分。Docker Client和Docker进行通话,Daemon完成重量级的任务,包括建立、运行、分发Docker容器。Client和Daemon可以运行在同一个物理机上,Client也可以连接一个远程的Daemon。Client和Daemon之间通过socket或者REST API进行通信。
Docker架构示意图如下:
- Docker Daemon
运行在宿主机(host machine)上,用户不直接与Docker进行交互,而是通过Docker Client进行连接。
- Docker Client
以docker:一个二进制文件的形式存在,是Docker的主要用户接口,它接受用户输入命令,并与Docker Daemon进行通信。
Docker的内部结构:
- Docker images(镜像)
一个Docker Image是一个只读的模板。比如,一个镜像可以是一个包含了Apache服务器的Ubuntu操作系统,并安装了你的应用程序。镜像用来创建Docker容器。Docker提供了一种简单的方式去创建一个新的镜像,或者更新镜像,或者下载别的用户已经创建好的镜像。Docker Image是Docker的建立模块。
- Docker registries(登记)
Docker registries管理镜像。registry对于用户上传、下载的镜像,或者标记为公有存储,或者标记为私有存储。公有的登记叫做Docker Hub。它提供了大量的现成镜像供用户使用。这些镜像可以是用户自己创建的,或者别人已经创建好的。Docker registries是Docker的发布模块。
- Docker containers(容器)
Docker containers和文件夹类似。一个Docker容器保存一个应用程序运行所需要的一切。每个容器都是基于一个镜像创建。Docker可以被运行、开始、停止、移动、删除。每个容器是一个独立、安全的应用程序平台。Docker container是Docker的运行模块。
Docker如何工作:
- 建立一个包含应用程序的镜像;
- 基于建立的镜像,创建一个Docker容器来运行应用程序;
- 可以通过公有的Docker Hub或者自己的登记来共享Docker镜像。
Docker组件如何工作:
- Docker镜像如何工作:
我们已经看到,Docker镜像是Docker容易创建时候用到的一个只读的模板。每个镜像由若干“层”构成,Docker镜像使用UnionFS将这些“层”整合成一个镜像。UnionFS允许文件和目录使用不同的文件系统(称为“分支”),各层之间透明叠加,构成一个整体、一致的文件系统。
Docker之所有这样轻量级与这些“层”有关,当需要修改一个镜像:比如将应用更新到一个新的版本——建立了一个新的“层”。在一个虚拟机里面,需要替换整个镜像,或者整个重新建立一个镜像;而Docker只需要将该新建层添加到镜像里面,或者做“层”更新即可。这样就不需要发布一个新的镜像,只需要更新一下,这样使得发布Docker镜像更快更简单。
每个镜像都起始于一个基础镜像,比如Ubuntu,一个基础的Ubuntu镜像,fedora,一个基础的fedora镜像。也可以使用用户自己制作的镜像作为一个基础镜像,比如用户创建一个Apache镜像,可以据此创建用户的Web应用镜像。
通常,Docker从Docker Hub上获取这些基础镜像。
之后,Docker镜像基于这些基础镜像,使用一组简单的、描述性的步骤——称之为“指令”。每个指令在镜像上创建一个新的“层”。指令包括如下的动作:
- 执行一个命令
- 添加一个文件或目录
- 创建一个环境变量
- 当基于当前镜像载入一个容器时,执行那个进程
这些指令被保存在一个叫做Dockerfile的文件里。当用户请求建立一个镜像时,Docker读取这些Dockerfile,执行里面的指令,然后返回一个最终的镜像。
- Docker登记如何工作:
Docker登记是对Docker镜像的一个管理库。当用户创建完一个Docker镜像之后,可以将镜像推送到公共的登记库Docker Hub,或者运行在防火墙内的个人登记库。
使用Docker Client可以搜索已经发布的Docker镜像,然后将镜像拖到本地的Docker host,基于这些镜像创建容器。
Docker Hub提供了公有和私有的镜像存储机制。公有镜像可以被任何人搜索、下载。私有镜像会在搜索结果中排除,并且只有你和你的用户可以下载镜像,基于他们创建容器。用户可以在这里创建一个存储计划。
- Docker容器如何工作:
一个容器包括:操作系统、用户添加的应用、元数据。每个容器都是基于镜像创建,镜像告诉Docker:容器包含哪些内容,
容器载入时运行哪些进程,以及其他多种配置数据。Docker镜像是只读的,当Docker运行一个容器,它会在只读的镜像上面添加一个“读写层”(使用之前提到的UnionFS),应用程序可以在这一层上运行。
- 运行一个容器的内部机制
用docker程序或者API,Docker Client通知Docker Daemon运行一个容器:
$ sudo docker run -i -t ubuntu /bin/bash
对上面的命令进行拆解:
Docker Client — 使用docker程序启动;
|- 使用run通知Docker Daemon载入一个新的容器;
|- ubuntu,容器基于那个镜像创建;
|- /bin/sh,容器载入完毕后,在容器内执行什么样的命令;
在载入容器的时候,至少要告诉Docker Daemon基于那个镜像创建容器,以及容器载入后执行什么样的命令。
上面这行命令执行的时候,内部的实现机制如下:
- 下载ubuntu镜像:Docker检查ubuntu镜像是否存在,如果本地不存在,就从Docker Hub下载;如果已经存在,就基于本地的ubuntu镜像创建容器;
- 创建一个新的容器:一旦拥有了镜像,就利用镜像创建容器;
- 分配一个文件系统并创建一个读写层:容器在这个文件系统里面创建,并且一个读写层添加到原有的基础镜像上;
- 分配 网络\网桥 接口:创建一个网络接口,允许容器与本地host通信;
- 分配IP地址:从资源池中寻找并绑定一个可用的IP地址;
- 执行用户指定的进程:运行你指定的应用;
- 捕获并提供应用程序输出:连接并记录标准输入、输出、报错,将这些信息提供给用户,供其了解应用程序如何运行。
拥有了一个运行的容器,之后用户可以管理容器,与应用程序交互,当运行结束后,关闭、移除容器。
Docker底层技术:
Docker用Go语言编写,利用了Linux内核的一些特性来提供我们看到的一些功能。
- Namespaces(名字空间)
Docker使用了叫做namespaces技术,来提供我们叫做容器的隔离工作区。当运行一个容器的时候,Docker为该容器创建一组namespaces。
这样就创建了一个隔离层:每个容器实例(aspect of container)运行在它自己的名字空间,且在外部无法对其访问。
Docker用到的一些名字空间包括:
-
- pid:Process ID,进程隔离;
- net:Networking,管理网络接口;
- ipc:InterProcess Communication,管理对IPC资源的访问;
- mnt:Mount,管理挂载点;
- uts:Unix Timesharing System,内核隔离及版本识别。
- Control groups(控制组)
隔离地运行应用程序的关键,是控制应用程序使用合法的资源。这保证容器在宿主机上是良好的多租客用户。控制组允许Docker共享宿主机的硬件资源给容器,并支持对容器可用资源进行限制和约束。比如,限制指定容器的可用内存。
Union file systems(联合文件系统)
联合文件系统,或者UnionFS,是一种特殊的文件系系统:通过创建“层”进行操作,这种文件系统够快,够轻巧。Docker使用联合文件系统提供容器的创建模块。Docker支持多种联合文件系统的变种,包括:AUFS, btrfs, vfs, and DeviceMapper
- Container format(容器格式)
Docker将这些组件打包成一个包装器,叫做容器格式。缺省的容器格式叫做libcontainer。Docker也支持使用LXC的传统Linux容器。未来,Docker将支出其他的容器格式,比如,与BSD Jails和Solaris Zones集成。
Reference:
https://docs.docker.com/introduction/understanding-docker/