Docker简介

历史与发展

2013年dotCloutd的PaaS服务商将内部项目Docker开源。这家公司随后出售PaaS,改名为Docker.Inc,专注Docker的开发与推广

Docker是一个开源的容器引擎,得益于容器技术带来的轻量级虚拟化,以及Docker在分层镜像应用上的创新,Docker在磁盘占用、性能和效率方面比传统虚拟化都有非常明显的提高,开始蚕食传统虚拟化的市场

加入Linux基金会,遵循Apache2.0协议,代码托管在GitHub

Docker省去传统虚拟化中的Hypervisor层,基于内核的Cgroup和Namespace技术与内核深度结合,性能与物理机接近

Docker不会直接与内核交互,通过Libcontainer交互,它才是真正的容器引擎

功能与组件

Docker客户端

Docker是C/S架构,Docker客户端通过command或REST API发起请求

Docker daemon

Docker server/Docker engine。驱动整个Docker功能的核心引擎。

接受客户端的请求并实现功能,涉及容器、镜像、存储,复杂的内部机制。

Docker容器

功能上,通过Libcontainer实现对容器生命周期的管理。

概念上,容器诠释了Docker集装箱的概念,可以存放任何货物,运到世界各地。

容器不是新的概念,牛逼的是Docker把容器封装之后,与集装箱的概念对应起来,是Docker把容器推广到全世界。

Docker镜像

与容器的动态对应,镜像是运行环境的静态体现。

相对于IOS镜像,轻量化,分层化,提供Dockerfile创建。

Registry

存放镜像的仓库,实现了镜像的传输中转站与版本管理。

官方Registry是Docker Hub,Registry是开源项目,自己可以搭建自己的Hub或二次开发。

概念澄清

Docker与LXC的关系

LXC(Linux Container):Docker 1.9之前使用的内核容器技术

Docker在LXC(Cgroup和Namespace)的基础上提供更高层的控制工具。包含以下重要特性:

  • 跨主机部署。LXC受限于机器的特定配置,Docker镜像定义了可移植的镜像。
  • 以应用为中心。简化应用的部署过程,在API、文档(这个真的要赞,Docker的文档是笔者读过最舒服的文档)、Dockerfile有体现。
  • 版本管理。类似于Git,镜像支持提交新的版本,回退版本,追踪镜像版本的功能。镜像的增量上传下载功能。
  • 组件重用。任何容器都可以用作生成另一个组件的镜像。
  • 共享。Registry。
  • 工具生态链。定义了API来定制容器创建和部署。非常多的工具能与Docker协作,扩展能力。

Libcontainer:Docker强大之后定义容器标准,在1.10之后用的内核容器技术库

Docker容器与虚拟机有什么区别

硬件虚拟化技术VS操作系统虚拟化技术

Hypervisor层VSCgroup和Namespace

容器与主机共享内核,不同容器之间可以共享部分系统资源。虚拟机独占分配给自己的资源,各个虚拟机之间完全隔离,因此更加重量级并更消耗资源。

启动速度:秒与数十秒

请根据具体需求判断使用相应的隔离方式

容器技术

相对独立的运行环境:进程的资源控制+访问隔离

一分钟理解容器

组成

容器 = Cgroup + Namespace + rootfs + 容器引擎(用户态工具)

Cgroup

control group,内核的特性,限制和隔离一组进程对系统资源(CPU、内存、IO、网络)的使用。

Namespace

将内核的全局资源做封装,使每个Namespace都有一份独立的资源,因此不同的进程在各自的Namespace内对同一种资源的使用不会相互干扰。

容器造就Docker

Docker的核心技术:容器?分层镜像?统一应用的打包与部署方式?“Build, Ship and Run"?

  • 微服务的设计艺术:轻量级虚拟化、与内核无缝结合的运行效率优势与极小的系统开销;将各个组件单独部署的思想。
  • 基于LXC容器技术的完善、加强、应用化

Docker镜像

Docker image概念

启动容器的只读模板

Docker image表示法:远程Registry地址/命名空间/仓库名:标签

Docker image的组织结构

1
2
3
4
5
6
7
8
9
10
11
12
13
vagrant@workshop:/var/lib/docker$ ll
total 76
drwxr-xr-x   9 root root  4096 May 18 15:16 ./
drwxr-xr-x  52 root root  4096 Nov 22  2015 ../
drwxr-xr-x   5 root root  4096 Nov 22  2015 aufs/
drwx------   3 root root  4096 May 18 15:16 containers/
drwx------ 258 root root 28672 May 17 15:51 graph/               #image各层的元数据
-rw-r--r--   1 root root  5120 May 18 15:16 linkgraph.db
drwxr-x---   3 root root  4096 Nov 22  2015 network/
-rw-------   1 root root  2015 May 17 15:51 repositories-aufs    #image总体信息
drwx------   2 root root  4096 May 18 13:59 tmp/
drwx------   2 root root  4096 Nov 22  2015 trust/
drwx------   3 root root  4096 May 17 15:39 volumes/

总体信息

1
2
3
4
5
6
vagrant@workshop:/var/lib/docker$ sudo cat repositories-aufs | python -m json.tool
{
    "Repositories": {
        "busybox": {
            "latest": "3d5bcd78e074f6f77b820bf4c6db0e05d522e24c855f3c2a3bbf3b1c8f967ba8"
        },

数据与元数据

graph目录包含本地镜像库中所有元数据与数据信息。对于busybox

1
2
3
4
5
6
7
root@workshop:/var/lib/docker/graph/3d5bcd78e074f6f77b820bf4c6db0e05d522e24c855f3c2a3bbf3b1c8f967ba8# ll
total 48
drwx------   2 root root  4096 Nov 22  2015 ./
drwx------ 258 root root 28672 May 17 15:51 ../
-rw-------   1 root root  1074 Nov 22  2015 json
-rw-------   1 root root     1 Nov 22  2015 layersize
-rw-------   1 root root    82 Nov 22  2015 tar-data.json.gz

Docker daemon可以通过这些信息还原出Docker image:先通过repositories-aufs获取image对应的layer ID,再根据layer对应的元数据梳理出image包含的所有层、层与层之间的关系,然后使用联合挂载技术还原出容器启动所需要的rootfs。

数据的组织

docker inspect对元数据(上个控制台输出的名称为json的文件)进行了整理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
root@workshop:/var/lib/docker/graph/3d5bcd78e074f6f77b820bf4c6db0e05d522e24c855f3c2a3bbf3b1c8f967ba8# docker inspect busybox
[
{
    "Id": "3d5bcd78e074f6f77b820bf4c6db0e05d522e24c855f3c2a3bbf3b1c8f967ba8",
    "RepoTags": [
        "busybox:latest"
    ],
    "RepoDigests": [],
    "Parent": "bf0f46991aed1fa45508683e740601df23a2395c47f793883e4b0160ab906c1e",
    "Comment": "",
    "Created": "2015-10-20T21:56:30.211245109Z",
    "Container": "e97e35122eefe587151947c737439860e06866ae6b5a5da785ec76caaa46441f",
    "ContainerConfig": {
        "Hostname": "3e10a20c1b67",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "/bin/sh",
            "-c",
            "#(nop) CMD [\"sh\"]"
        ],
        "Image": "bf0f46991aed1fa45508683e740601df23a2395c47f793883e4b0160ab906c1e",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": null
    },
    "DockerVersion": "1.8.2",
    "Author": "",
    "Config": {
        "Hostname": "3e10a20c1b67",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": false,
        "AttachStderr": false,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": null,
        "Cmd": [
            "sh"
        ],
        "Image": "bf0f46991aed1fa45508683e740601df23a2395c47f793883e4b0160ab906c1e",
        "Volumes": null,
        "WorkingDir": "",
        "Entrypoint": null,
        "OnBuild": null,
        "Labels": null
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Size": 0,
    "VirtualSize": 1112855,
    "GraphDriver": {
        "Name": "aufs",
        "Data": null
    }
}
]

Id:最上层的layerID Parent:该layer的父层,这样就可以找到某个image的所有layer

Docker image扩展知识

联合挂载

把多个目录挂载到同一个目录,对外呈现这些目录的联合

只有OverlayFS在2014年合入Linxu主线,aufs只有ubuntu支持,Redhat和Suse采用devicemapper,请根据实际情况选择后端存储驱动

写时复制

操作系统的fork:当父进程fork子进程,内核不会马上分配内存,而是让父子进程共享内存。当两者之一修改共享内存时,会触发一次缺页异常导致真正的内存分配。加速了创建速度与减少了内存的消耗。

所有的容器共享某个image的文件系统,所有数据都从image中读取,只有当要对文件进行写操作时,才从image里把要写的文件复制到自己的文件系统进行修改。从而提高加载速度并节省空间

存在的问题

  • image难以加密。image是共享的,加密会导致难以共享。有notary的镜像签名机制。
  • image分层之后有大量元数据。分布式存储对小文件的支持不好。
  • image制作完成之后无法修改。Dockre不提供修改或合并层的指令。

号外号外

最近在总结一些针对Java面试相关的知识点,感兴趣的朋友可以一起维护~
地址:https://github.com/xbox1994/2018-Java-Interview

Comments