一、什么是docker

1.1、docker起源

Docker是一个开源的应用容器引擎,基于Go语言 ,诞生于2013年初。 最初发起者是DotCloud公司((Platform-as-a-Service, PaaS)提供商)开源的一个基于 LXC 的高级容器引擎。 功能Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器;实现虚拟化。 主要工作如拉取镜像、编译镜像、运行容器、发布容器等。

1.2、docker的版本

Docker从1.13.x(2017.3.2)版本开始,版本分为企业版EE和社区版

  • CE EE(Enterprise Edition: 企业版):2017 年 3 月 2 日发布17.03;大公司(含自研)
  • CE(Community Edition: 社区版):2017 年 3 月 2 日发布17.03; 中小企业使用居多

从 17.03开始基于时间线进行版本发布, 17.03 代表17年3月,说明这个是个稳定版。

  • CE:"Edge"与"Stable"两个版本发行 Edge(边界)版本每月发布,提供一个月支持。
  • Stable(稳定)版本每季度发布,提供4个月支持
  • EE :每个季度发布一次 季度版本, 也就是说每年会发布4个季度版本

1.3、docker解决了什么问题

docker解决了软件环境部署复杂的问题。对于一个传统的软件工程,开发人员把写好的代码放到服务器上去运行是一件很头疼的事情,因为常常会出现环境不兼容而导致各种各样的bug。

比如说,开发是windows系统下编写的代码,放到linux服务器上可能会出问题,开发在本地依赖了一个系统自带的驱动,服务器上却没有这个驱动,开发在本地设置了很多环境变量,服务器上又得重新设置。

在软件部署的时候,经常会发生在这台机器上可以跑,但是在另一台机器上却运行失败的情况。运维人员需要不断在开发环境和服务器环境之间调试。

有了docker,只需要简单的几行命令,就可以做到所有运行环境都一致。

1.4、docker和虚拟机的关系

说到docker,那就必须要和虚拟机做一下比较,其实docker是和虚拟机是类似的东西,我们应该知道虚拟机就是在我们的操作系统上虚拟出来一个电脑,然后里边可以安装、运行各种各样的软件,和我们真的电脑是差不多的,我们可以拿着这个虚拟好的电脑(其实是一个文件)在按了虚拟机的其他电脑上可以直接运行,里边的东西就不用我们来回安装和配置了,也是很方便的。

docker其实提供的也是这么一种的技术,只不过它比虚拟机效率更加的高,启动快,占用资源小等一系列的优点,而且虚拟机比较笨重,这是因为虚拟机和docker来实现思想上有本质的区别,我们可以通过下边的图对比一下:

虚拟机的运作原理:是虚拟电脑的硬件资源,把硬件资源分配出来,然后虚拟出来多个操作系统,虚拟出来的是一个完整的电脑。

特性 容器 虚拟机
启动 秒级 分钟级
硬盘使用 一般为MB 一般为GB
性能 接近原生 弱于
系统支持量 单机支持上千个容器 一般几十个

相同点:

  1. 容器和虚拟机一样,都会对物理硬件资源进行共享使用。
  2. 容器和虚拟机的生命周期比较相似(创建、运行、暂停、关闭等等)。
  3. 容器中或虚拟机中都可以安装各种应用,如redis、mysql、nginx等。也就是说,在容器中的操作,如同在一个虚拟机(操作系统)中操作一样。
  4. 同虚拟机一样,容器创建后,会存储在宿主机上:linux上位于/var/lib/docker/containers下

不同点:

  1. 虚拟机的创建、启动和关闭都是基于一个完整的操作系统。一个虚拟机就是一个完整的操作系统。而容器直接运行在宿主机的内核上,其本质上以一系列进程的结合。
  2. 容器是轻量级的,虚拟机是重量级的。首先容器不需要额外的资源来管理(不需要Hypervisor、Guest OS),虚拟机额外更多的性能消耗;其次创建、启动或关闭容器,如同创建、启动或者关闭进程那么轻松,而创建、启动、关闭一个操作系统就没那么方便了。
  3. 也因此,意味着在给定的硬件上能运行更多数量的容器,甚至可以直接把Docker运行在虚拟机上。

二、docker的核心概念

2.1、Docker镜像(Image)

镜像到底是个什么东西呢,很多人在学习docker的时候都是一头雾水的,可是是歪果仁对镜像情有独钟吧,好多东西都有镜像的概念。比如我们安装系统的.iso文件,其实就是镜像,这里你就可以把镜像认为是一种模板。我们可以使用docker根据这个模板创建容器来运行,其实更可以理解为镜像是好比github上的仓库一样,我们可以克隆下来源代码然后运行,运行起来的代码可以是一个网站、一个应用程序啥的,这就可以叫做容器。说白了,镜像就是一堆静态的模板,运行起来的镜像就是容器。镜像一般需要我们拉取下来,是只读的,这个我们克隆github上的仓库是一样一样的。

docker镜像中有分层的概念,就是一个镜像可能基于好几个镜像,比如一个web运行环境可能需要操作系统ubuntu、数据库mysql、.net core runtime运行时,那我们拉取的这个镜像就会包好这好几个镜像,这就好像我们前边说的打包好的运行环境一样,直接就拉下来一个小电脑一样。

总结起来就是docker镜像就是我们事先做好的一套版本,里面装载着我们所需要的东西和流程,模板之间还可以嵌套。

2.2、容器(Container)

当我们拉取了一个镜像,然后run一下,就会根据这个镜像运行出来一个容器,运行的容器就好像我们的应用程序一样,可以访问可以停止,我们运用多次run命令,就运行了很多很多容器,也可以说是镜像的实例。从这个角度来看,我们可以把镜像看作是类,容器看作new出来的实例,也是很合适的。

2.3、仓库(Repository)

存放镜像的地方就是仓库,就好比存放代码的地方是github一样,我们就把github称为代码的仓库,github算是最大的仓库。那么存放docker镜像的地方我们叫做dockerhub,是docker的中央仓库。其实已经有dockerhub这个网站了(https://hub.docker.com/),这就是 存放docker镜像的官方仓库,好多官方的也保存在这里,保证了镜像的安全性和可靠性,我们可以从上边拉取一下镜像来运行我们的软件。当然我们也可以制作好我们自己镜像推送上去,不过这些肯定是要官方审核的,防止有些人写入一些恶意代码。不过我们可以推到我们自己的dockerhub上去,供我们自己使用,这个就好我们的github账号一样了,属于私有镜像了。

2.4、数据卷(Volumn)

实际上我们的容器就好像是一个简易版的操作系统,只不过系统中只安装了我们的程序运行所需要的环境,前边说到我们的容器是new出来的实例,既然是new出来的实例那就会销毁,那如果销毁了我们的程序产生出的需要持久化的数据怎么办呢,容器运行的时候我们可以进容器去查看,容器一旦销毁就什么都没有了。所以数据卷就是来解决这个问题的,是用来做数据持久化到我们的宿主机上容器间的数据共享,简单的说就是将宿主机的目录映射到容器中的目录,应用程序在容器中的目录读写数据会同步到宿主机上,这样容器产生的数据就可以持久化了,比如我们的数据库容器,就可以把数据存到我们宿主机上的真实磁盘上了。

2.5、docker镜像、容器、仓库、数据卷关系示意图

三、docker的底层原理

3.1、docker调用流程图

Docker使用C/S架构,Docker Client通过command(or api)与Docker Daemon(Sever进程)通信实现容器的构建。

用户访问docker的流程,用户并不是直接和docker的守护进程交互,而是通过Docker client和docker的守护进程交互。

tips:

Docker Client和Docker Daemon之间通过在Socket上使用RESTful API进行交互,所以Docker Client和Docker Daemon可以运行在同一个系统上也可以通过远程的方式访问总体

docker总体架构示意图:

1、用户是使用 Docker Client 与 Docker Daemon 建立通信,并发送请求给后者。

2、Docker Daemon 作为 Docker 架构中的主体部分,首先提供 Docker Server 的功能使其可以接受 Docker Client 的请求。

3、Docker Engine 执行 Docker 内部的一系列工作,每一项工作都是以一个 Job 的形式的存在。

4、Job 的运行过程中,当需要容器镜像时,则从 Docker Registry 中下载镜像,并通过镜像管理驱动 Graphdriver 将下载镜像以 Graph 的形式存储。

5、当需要为 Docker 创建网络环境时,通过网络管理驱动 Networkdriver 创建并配置 Docker容器网络环境。

6、当需要限制 Docker 容器运行资源或执行用户指令等操作时,则通过 Execdriver 来完成。

7、Libcontainer 是一项独立的容器管理包,Networkdriver 以及 Execdriver 都是通过 Libcontainer 来实现具体对容器进行的操作。

3.2、docker各个模块组件分析

3.2.1、Docker Client「发起请求」

1、Docker Client是和Docker Daemon建立通信的客户端。用户使用的可执行文件为docker(一个命令行可执行文件),docker命令使用后接参数的形式来实现一个完整的请求命令(例如:docker images,docker为命令不可变,images为参数可变)。

2、Docker Client可以通过以下三种方式和Docker Daemon建立通信:tcp://host:port、unix://pathtosocket和fd://socketfd。

3、Docker Client发送容器管理请求后,由Docker Daemon接受并处理请求,当Docker Client接收到返回的请求相应并简单处理后,Docker Client一次完整的生命周期就结束了。(一次完整的请求:发送请求→处理请求→返回结果),与传统的C/S架构请求流程并无不同。

3.2.2、Docker Daemon(后台守护进程)

Docker daemon架构图:

Docker Server架构图: 

1、Docker Server相当于C/S架构的服务端。功能为接受并调度分发DockerClient发送的请求。接受请求后,Docker Server通过路由与分发调度,找到相应的Handler来执行请求。

2、在Docker的启动过程中,通过包gorilla/mux创建了一个mux.Router来提供请求的路由功能。在Golang中gorilla/mux是一个强大的URL路由器以及调度分发器。该mux.Router中添加了众多的路由项,每一个路由项由HTTP请求方法(PUT、POST、GET或DELETE)、URL、Handler三部分组成。

3、创建完mux.Router之后,Docker将Server的监听地址以及mux.Router作为参数来创建一个httpSrv=http.Server{},最终执行httpSrv.Serve()为请求服务。

4、在Docker Server的服务过程中,Docker Server在listener上接受Docker Client的访问请求,并创建一个全新的goroutine来服务该请求。在goroutine中,首先读取请求内容并做解析工作,接着找到相应的路由项并调用相应的Handler来处理该请求,最后Handler处理完请求之后回复该请求。

3.2.3、Docker Engine

1、Docker Engine是Docker架构中的运行引擎,同时也Docker运行的核心模块。它扮演DockerContainer存储仓库的角色,并且通过执行Job的方式来操纵管理这些容器。

2、在Docker Engine数据结构的设计与实现过程中,有一个Handler对象。该Handler对象存储的都是关于众多特定Job的Handler处理访问。举例说明:DockerEngine的Handler对象中有一项为:{“create”:daemon.ContainerCreate,},则说明当名为”create”的Job在运行时,执行的是daemon.ContainerCreate的Handler。

3.2.4、Job

1、一个Job可以认为是Docker架构中Docker Engine内部最基本的工作执行单元。Docker可以做的每一项工作,都可以抽象为一个Job。例如:在容器内部运行一个进程,这是一个Job;创建一个新的容器,这是一个Job。Docker Server的运行过程也是一个Job,名为Serve Api。

2、Job的设计者,把Job设计得与Unix进程相仿。比如说:Job有一个名称、有参数、有环境变量、有标准的输入输出、有错误处理,有返回状态等。

3.2.5、DockerRegistry(镜像注册中心)

1、DockerRegistry是一个存储容器镜像的仓库(注册中心),可理解为云端镜像仓库。按Repository来分类,dockerpull按照[repository]:[tag]来精确定义一个具体的Image。

2、在Docker的运行过程中,Docker Daemon会与Docker Registry通信,并实现搜索镜像、下载镜像、上传镜像三个功能,这三个功能对应的Job名称分别为:“search”、”pull”与“push”。

3、Docker Registry可分为公有仓库(Docker Hub)和私有仓库。

3.2.6、Graph(Docker 内部数据库)

Repository:

1、已下载镜像的保管者(包括下载的镜像和通过Dockerfile构建的镜像)。

2、一个Repository表示某类镜像的仓库(例如:Ubuntu),同一个Repository内的镜像用Tag来区分(表示同一类镜像的不同标签或版本)。一个Registry包含多个Repository,一个Repository包含同类型的多个Image。

3、镜像的存储类型有Aufs、Devicemapper、Btrfs、Vfs等。其中CentOS系统7.x以下版本使用Devicemapper的存储类型。

4、同时在Graph的本地目录中存储有关于每一个的容器镜像具体信息,包含有:该容器镜像的元数据、容器镜像的大小信息、以及该容器镜像所代表的具体rootfs。

GraphDB:

1、已下载容器镜像之间关系的记录者。

2、GraphDB是一个构建在SQLite之上的小型数据库,实现了节点的命名以及节点之间关联关系的记录。

3.2.7、Driver(执行部分)

Driver是Docker架构中的驱动模块。通过Driver驱动,Docker可以实现对Docker容器执行环境的定制。即Graph负责镜像的存储,Driver负责容器的执行。

Graphdriver:

Graphdriver架构图

1、Graphdriver主要用于完成容器镜像的管理,包括存储与获取。

2、存储:dockerpull下载的镜像由Graphdriver存储到本地的指定目录(Graph中)。

3、获取:dockerrun(create)用镜像来创建容器的时候由Graphdriver到本地Graph中获取镜像。

Networkdriver:

Networkdriver架构图

Networkdriver的用途是完成Docker容器网络环境的配置,其中包括:

  • Docker启动时为Docker环境创建网桥。
  • Docker容器创建时为其创建专属虚拟网卡设备。
  • Docker容器分配IP、端口并与宿主机做端口映射,设置容器防火墙策略等。

Execdriver:

Execdriver架构图

1、Execdriver作为Docker容器的执行驱动,负责创建容器运行命名空间、容器资源使用的统计与限制、容器内部进程的真正运行等。

2、现在Execdriver默认使用Native驱动,不依赖于LXC。

3.2.8、Libcontainer(函数库)

Libcontainer架构图:

1、Libcontainer是Docker架构中一个使用Go语言设计实现的库,设计初衷是希望该库可以不依靠任何依赖,直接访问内核中与容器相关的API。

2、Docker可以直接调用Libcontainer来操纵容器的Namespace、Cgroups、Apparmor、网络设备以及防火墙规则等。

3、Libcontainer提供了一整套标准的接口来满足上层对容器管理的需求。或者说Libcontainer屏蔽了Docker上层对容器的直接管理。

3.2.9、Docker Container(服务交付的最终形式)

Docke rContainer架构

1、DockerContainer(Docker容器)是Docker架构中服务交付的最终体现形式。

2Docker按照用户的需求与指令,订制相应的Docker容器:

  • 用户通过指定容器镜像,使得Docker容器可以自定义rootfs等文件系统。
  • 用户通过指定计算资源的配额,使得Docker容器使用指定的计算资源。
  • 用户通过配置网络及其安全策略,使得Docker容器拥有独立且安全的网络环境。
  • 用户通过指定运行的命令,使得Docker容器执行指定的工作。

3.3、Docker镜像下载原理剖析

index:GET /v1/repositories/(namespace)/(repo_name)/images 【docker pull调用】

关键名词解释:

index服务(Open API):主要提供镜像索引以及用户认证的功能。

当下载一个镜像的时候,首先会去index服务上做认证,然后index服务查找镜像所在的registry的地址,具体流程如下:

  1. docker首先查询index,看哪里可以下载nginx;
  2. index返回nginx的image List、registry URL和token;
  3. docker向registry请求数据;
  4. registry向index验证token/user是否可以下载该image;
  5. index返回验证结果true/false ;
  6. registry给docker返回image数据。

3.4、镜像分层与文件系统深入剖析

3.4.1、联合文件系统

UnionFS( 联合文件系统):Union文件系统(UnionFS )是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtualfilesystem)。Union文件系统是Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。

Docker 中使用的 AUFS(AnotherUnionFS)就是一种联合文件系统。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。

Docker 目前支持的联合文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

3.4.2、base镜像

base 镜像简单来说就是不依赖其他任何镜像,完全从0开始建起,其他镜像都是建立在他的之上,可以比喻为大楼的地基,docker镜像的鼻祖。

base 镜像有两层含义:(1)不依赖其他镜像,从 scratch 构建;(2)其他镜像可以之为基础进行扩展。

所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。

3.4.3、Docker镜像加载原理

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统就是UnionFS。

典型的 Linux 启动到运行需要两个FS,bootfs + rootfs:

在Docker镜像的最底层是bootfs,然后是rootfs。

bootfs(boot file system):Docker镜像的最底层是bootfs,用户是不能对这层作任何修改,主要包含bootloader和kernel,bootloader 主要是引导加载kernel,Linux刚启动时会加载bootfs文件系统。

rootfs (root file system):在 bootfs 上一层是 rootfs,我们也称之为 base image layer(FROM centos)。

我们以nginx为例:

下载完成以后依次执行下面命令:

#创建downloadimage,用于储存docker的image
mkdir -p /usr/local/downloadimage
#切换目录
cd /usr/local/downloadimage
#将docker的nginx镜像保存为nginx.tar文件
docker save nginx > nginx.tar

保存完成之后我们打开nginx.tar文件,其结构如下所示:

然后我们可以打开manifest.json文件,查看其结构:

manifest :描述文件,主要存在于registry中作为docker镜像的元数据文件,在pull、push、 save、load中作为镜像结构和基础信息的描述文件。

  1. manifest里面重要两部分内容,一是image的配置文件config,另一个是image包含的所有 filesystem layer的digest(sha256);
  2. 遍历manifest里面的所有layer,根据其digest在本地找,如果找到对应的layer,则跳过当前 layer,否则从服务器取相应layer的压缩包;
  3. 等上面的所有步骤完成后,就会拼出完整的image。

那么layer之间的层级是怎么界定的呢?每个layer文件夹下都有一个json的文件,层级关系信息都隐藏在这个信息里面。

从图上可以看出,每个layer都是通过json文件中的parent去信息去查找自己的上一层信息的,因此,我们可以得出nginx镜像的整体层级关系如下所示:

3.4.4、docker镜像下载流程

上一小节我们知道了docker镜像分层原理,docker的每一层layer合起来就是一个镜像,那么假如有两个image使用了同一个layer,那么这个layer会重复下载吗?答案是不会的,docker镜像下载的流程如下:

  1. docker client发送镜像的tag到registry。
  2. registry根据镜像tag,得到镜像的manifest文件,返回给docker client。
  3. docker client拿到manifest文件后,根据其中的config的digest,也就是image ID,检查下镜像在本地是否存在。
  4. 如果镜像不存在,则下载config文件,并根据config文件中的diff_ids得到镜像每一层解压后的digest。
  5. 然后根据每层解压后的digest文件,检查本地是否存在,如果不存在,则通过manifest文件中的layer的digest下载该层并解压,然后校验解压后digest是否匹配。
  6. 下载完所有层后,镜像就下载完毕。

3.4、Docker容器生命周期管理

docker run:创建一个新的容器并运行一个命令;
docker start/stop/restart:启停容器;
docker kill:杀掉运行中的容器;
docker rm:删除一个或多个容器;
docker pause/unpause:暂停或恢复容器中的所有进程;
docker create:创建一个新的容器但不启动它;
docker update:更新一个或多个容器的配置;

3.5、底层核心技术之容器隔离

Docker主要就是借助 Linux 内核技术Namespace来做到隔离的,Linux Namespaces机制提供一种资源隔离方案。PID,IPC,Network等系统资源不再是全局性的,而是属于某个特定的Namespace。每个namespace下的资源对于其他namespace下的资源都是透明,不可见的,因此在操作系统层面上看,就会出现多个相同pid的进程。系统中可以同时存在两个进程号为0,1,2的进程,由于属于不同的namespace,所以它们之间并不冲突。而在用户层面上只能看到属于用户自己namespace下的资源,例如使用ps命令只能列出自己namespace下的进程。这样每个namespace看上去就像一个单独的Linux系统。

目前,Linux 内核实现了6种 Namespace:

  • UTS Namespace:对主机名和域名进行隔离。为什么要隔离主机名?因为主机名可以代替IP来访问。如果不隔离,同名访问会出冲突。
  • IPC Namespace:Linux提供很多种进程通信机制,IPC Namespace针对SystemV和POSIX消息队列,这些IPC机制会使用标识符来区别不同的消息队列,然后两个进程通过标识符找到对应的消息队列。IPC Namespace使得相同的标识符在两个Namespace代表不同的消息队列,因此两个Namespace中的进程不能通过IPC来通信。
  • PID Namespace:PID Namespace用来隔离进程的PID空间,使得不同PID Namespace里的进程PID可以重复且互不影响。PID Namespace对容器类应用特别重要,可以实现容器内进程的暂停/恢复等功能,还可以支持容器在跨主机的迁移前后保持内部进程的PID不发生变化。
  • Mount Namespace:为进程提供独立的文件系统视图。可以这么理解,Mount Namespace用来隔离文件系统的挂载点,这样进程就只能看到自己的Mount Namespace中的文件系统挂载点。进程的Mount Namespace中的挂载点信息可以在/proc/[pid]/mounts、/proc/[pid]/mountinfo和/proc/[pid]/mountstats这三个文件中找到。在一个Namespace里挂载、卸载的动作不会影响到其他Namespace。
  • Network Namespace:在逻辑上是网络堆栈的一个副本,它有自己的路由、防火墙规则和网络设备。默认情况下,子进程继承其父进程的Network Namespace。每个新创建的Network Namespace默认有一个本地环回接口lo,除此之外,所有的其他网络设备(物理/虚拟网络接口,网桥等)只能属于一个Network Namespace。每个socket也只能属于一个Network Namespace。
  • User Namespace:用于隔离安全相关的资源,包括userIDsandgroupIDs,keys,和capabilities。同样一个用户的userID和groupID在不同的User Namespace中可以不一样(与PID Namespace类似)。可以这样理解,一个用户可以在一个User Namespace中是普通用户,但在另一个User Namespace中是root用户。

3.6、底层核心技术之资源控制

docker的底层是通过CGroup控制的。

CGroup:Control Groups的缩写,是Linux内核提供的一种可以限制、记录、隔离进程组(process groups)所使用的物理资源(如cpu memory i/o等等)的机制。

Cgroup作用:控制程序对资源的占用。

CGroup技术可以被用来在操作系统底层限制物理资源,起到Container的作用。图中每一个JVM进程对应一个ContainerCgroup层级,通过CGroup提供的各类子系统,可以对每一个JVM进程对应的线程级别进行物理限制,这些限制包括CPU、内存等等许多种类的资源。那么,docker是如何来定义容器使用的资源呢?

3.6.1、要求容器CPU使用权重为512

需求:要求容器 CPU 使用权重为512

/sys/fs/cgroup 为资源限制的目录

1. cat /sys/fs/cgroup/cpu/cpu.shares    //查看宿主机CPU的权重
2. docker run -d  dc833dc45d8f               //运行一个容器或者进入交互式容器
docker exec  -it 17f274c2ca9d  /bin/bash
​3. cat /sys/fs/cgroup/cpu/cpu.shares //查看容器中CPU的权重  发现和宿主机一样
4. exit                               //退出容器
​
​
docker stop id
docker rm id
​
5. docker run   -d  -c 512 dc833dc45d8f
6. cat /sys/fs/cgroup/cpu/cpu.shares  //查看修改后容器中CPU的权重 

结论:

CPU 和容器的 CPU权重都是 一样的 1024

如果不进行修改 CPU 的权重,那么容器与宿主机对 CPU 的权重都是默认的1024,这样分配是不合理的,因为宿主机与容器对 CPU 的权重一样,因而导致,它们在对 CPU 资源出现抢占的情况下,其可使用的 CPU 资源是 1:1

若限制容器为512,宿主机还是 1024,那么其CPU 使用权重的比例就变成了 2:1,可以通过上面对容器进行限制:

总结

使用 Cgroup,可更好地根据任务和用户分配硬件资源(CPU、内存、交换空间、写入速度)。

3.6.2、写入速度限制在 40MB 以内

time dd if=/dev/zero of=a.txt bs=1M count=200 oflag=direct
  • time dd:是 Linux 读写速率测试命令;
  • if=file:输入文件名 标准输入确省;
  • of=file:输出文件名,标准输出确省;
  • bs=n:同时设置输入输出块大小;
  • count:指定数量的输入块;
  • oflag:写入方式:读写数据采用直接 IO 方式 ;

容器中执行

因网络原因,每次执行效果不大一样

宿主机执行

因网络原因,每次执行效果不大一样

限速

可以看到,如果不对其进行限制,那么会使用宿主机最大的写速度,那么怎么限制呢

docker run -d  --name czbk1 --device-write-bps /dev/sda:40MB   dc833dc45d8f
​
进入到容器内部验证
time dd if=/dev/zero of=a.txt bs=1M count=200 oflag=direct

这样的话,就可以将容器的写入速度限制在了 40mb 左右

3.6.3、多任务按比例分享CPU

当多个容器任务运行时,很难计算CPU的使用率,为了使容器合理使用CPU资源,可以通过  --CPU-shares选项设置容器按比例共享CPU资源,这种方式还可以实现cpu使用率的动态调整

例如:运行三个新的容器A,B,C,占用cpu资源为1:1:2。

docker run --name A -itd --cpu-shares 1024 centos /bin/bashdocker run --name B -itd --cpu-shares 1024 centos /bin/bashdocker run --name C -itd --cpu-shares 2048 centos /bin/bash

如果又一个容器D需要更多的cpu资源,则可以将其 --cpu--shares的值设置为4096,那么ABCD的cpu资源比例为1:1:2:4。

3.7、Docker容器网络管理深入剖析

Docker 安装完成后缺省配置有三个网络类型

使用 Docker network ls 可以查看当前系统中的 Docker 网桥

#查看docker的网桥
docker network ls

Docker 内置这三个网络,运行容器时,你可以使用该 --network 标志来指定容器应连接到哪些网络。

3.7.1、bridge(默认)

bridge(默认):此模式会为每一个容器分配、设置 IP等,并将容器连接到一个docker0 虚拟网桥

docker  inspect 1d6f1cb322b3

3.7.2、none

none Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置 IP 等

#创建一个使用none 网络的容器
docker run -d --name "none-network" --network=none  941109e2896d

缺点是:无法联网

优点是:封闭的网络能很好的保证容器的安全性,适用于企业开发

应用场景:生成密钥

3.7.3、host

相当于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立IP地址。

容器将不会虚拟出自己的网卡,也不会配置自己的IP等,而是使用宿主机的IP和端口。

#创建一个使用none 网络的容器
docker run -d --name "host-network" --network=host  941109e2896d

使用 host 模式的容器可以直接使用宿主机的 IP 地址与外界通信,容器内部的服务端口也可以使用宿主机的端口

缺点:网络的隔离性不好

2.7.4、Containers

什么是Containers?

  1. 当前网络下所有的容器(正在运行的);
  2. 如果容器停止,Containers就不存在容器的信息。
  • 查看网络详细信息,以及网络下所有的容器信息

bridge 也是所有 container 的缺省网络

docker network inspect bridge 

2.7.5、容器间网络通信

ifconfig 可以查看 docker0 网卡的地址为 inet 172.18.0.

注意:如果没有ifconfig,可以使用ip addr或者是执行yum install net-tools命令安装ifconfig命令

用户定义的网络

docker network create --subnet=172.128.0.0/16  czbkNetwork-bas

在 IP 地址后加上 "/" 符号以及 1-32 的数字,其中 1-32 的数字表示子网掩码中网络标识位的长度

自定义网络对应的网卡

每一个自创建的网络,在主机上都有一个 "br-" 开头;这和缺省 bridge 网络一样,只不过 bridge 不以 br- 开头,而自定义的网络使用 br- 开头罢了:

ifconfig

自定义网络czbkNetwork对应的网卡br-413b460a0fc8 

2.7.6、docker网络通信常见问题

1、如何知道自定义网络下有哪些用户容器?

docker inspect czbkNetwork

2、如何知道自定义网络(czbkNetwork)对应的网卡是那个?

docker  network  inspect  czbkNetwork

我们可以看到网关地址是 172.188.0.1 那么 172.188.0.1 是谁呢,前面我们已经知道了,就是自定义网卡的地址

ifconfig

结论:网卡br-413b460a0fc8 是属于czbkNetwork网络的

3、Docker 容器相互访问以及容器是如何访问互联网的

也就是说默认情况下容器会使用docker0这个网桥,两个容器都使用这个网桥的话,就可以直接互相访问了。

然后我们Docker的容器里面访问互联网的时候,其实也是使用docker0网卡转换到宿主机网卡上,然后访问互联网。

4、互联网怎么访问 Docker?

互联网通过Docker暴露的端口访问Docker。

【docker】docker介绍相关推荐

  1. docker 感性介绍

    docker 感性介绍 Docker 允许开发者们将他们的应用打包放在云端的"容器"中,无需再修改就可以发布到任何流行的 Linux 机器上.由于采用沙盒机制,各应用之间没有任何接 ...

  2. Docker教程介绍

    Docker教程介绍 教程环境准备 linux 系统 virtualbox 软件安装 教程介绍 0-安装Vagrant,安装 centos 系统. 1-docker 介绍 2-docker 安装 3- ...

  3. Docker 基础介绍及配置安装 [一]

    Docker 基础介绍及配置安装 [一] Docker 基础介绍及配置安装 [一] Docker 时间:2016年11月2日 Docker介绍 Docker是Docker.lnc公司开源的一个基于LX ...

  4. docker命令介绍,镜像制作,容器启动,进入容器操作等

    1:在linux安装docker环境一键安装命令: curl -sSL https://get.daocloud.io/docker | sh 2:查看 Docker 是否安装成功: docker v ...

  5. Docker之介绍与安装

    Docker 说明 本章,我们主要从Docker简介.Docker中几个核心概念和Docker安装这几个方面对Docker进行介绍! 1.

  6. docker原理介绍以及部署使用

    docker原理介绍以及部署使用 1. docker简介 2. docker架构概念 3. docker安装部署 3.1 安装环境 3.2 安装步骤 4. docker使用 4.1 镜像管理 4.2 ...

  7. docker简单介绍、安装使用、常用命令、docker构建springboot项目、k8s安装

    docker简单介绍 docker的意义 把事情简单化 Docker友好的基于CLI的工作流使各种技能水平的开发人员都可以访问构建,共享和运行容器化应用程序. 快速移动 从单个软件包安装即可在几分钟内 ...

  8. docker容器介绍(3)

    接上篇docker容器介绍 镜像迁移 保存一台宿主机上的镜像为tar文件,然后可以导入到其他的宿主机上: save ​ 将镜像打包,与下面的load命令相对应 [root@yixuan ~]# doc ...

  9. docker 详细介绍安装步骤以及简单的运用

    目录 一,docker的简单介绍 二,docker的安装步骤 Centos7安装 1.确定版本是否是Centos7以上 2.卸载旧版docker (如果有的话) 3.安装一些软件 4.设置docker ...

  10. Docker学习(一)-----Docker全面介绍

    Docker简介 Docker是一种遵从Apache2.0协议开源的Linux容器管理解决方案,它通过进程和进程通信技术对操作系统的文件资源和网络的进行隔离,实现了包含文件资源.系统资源(shell环 ...

最新文章

  1. ceph nautilus相对于minic的主要改动
  2. MNE-Python : TypeError: today() takes no keyword arguments
  3. asp.net传递参数
  4. STL中的list详解
  5. ASCII码对应表chr(9)、chr(10)、chr(13)、chr(32)、chr(34)、chr(39)、chr(.. 以及oracle中使用chr
  6. iOS 地图定位 定位
  7. 关于我的代码在课上第一时间没有运行出来这件事
  8. centos安装python3.7.0过程记录
  9. cesium 取消光晕
  10. dataguard如何实现切换_ORACLE dataguard 切换
  11. Spring Boot 三大开发工具,你都用过几个?
  12. oracle binlog同步,系统设计 | 通过Binlog来实现系统间数据同步
  13. html日历修改,HTML精美日历插件
  14. 专题开发十三:JEECG微云高速开发平台-附录
  15. java编程加载窗口,插入图片
  16. 数据产品经理——数据指标
  17. Windows Server 2019系统Windows defender误删文件的解决办法
  18. int int int * int**的区别、联系和用途
  19. 在线学习算法FTRL基本原理
  20. 解决mac终端放大字体重启又变小了

热门文章

  1. 网页收录数量与网站排名有关系吗?
  2. Tomcatnbsp;Servletnbsp;JSPamp;nbs…
  3. Linux中修改用户UID和组GID的方法
  4. Visual Studio 2013 不小心关掉“解决方案资源管理器”怎么办?
  5. /etc/fstab 只读无法修改的解决办法
  6. 图解HIVE页面单跳转化率
  7. 【Node.js】初识Node.js
  8. EPSON ESC/POS打印机指令
  9. SpringBoot——安全管理(一)
  10. 性能:如何减少延迟提升内存分配效率