前言第一趴---Docker容器圈简介第二趴---Docker基本操作容器圈容器这个新生事物,现在还可以说是新生事物吗?对于我们学生而言,我觉得没毛病,你说呢? 容器技术可说重塑了整个云计算市场的形态,带动了一批年轻有为的容器技术儿,不过「容器」这个概念是 Docker 公司发明的么,不是,它只是众多 Paas 项目中的最底层,没人关注的那一部分而已。
Paas 项目之所会被很多公司所接受,自然是因为解放了部分开发人员的劳动力,尽快干玩活儿早点下班。其依赖的就是「应用托管」的能力,在电脑上斗过地主的应该知道,托管了以后就会自动出牌,同样的道理,为了尽量的弥补本地和云上的环境差异,就出现了 Paas 开源项目。 举个例子来说,运维人员小仙云上部署一个 Cloud Foundry 项目,开发人员只需要简单的一行代码就可以实现将本地的应用部署到云上 就这样一行代码就实现了将本地应用上传到云上,属实很轻松。
实际上,我们可以将其最核心的组件理解为一套应用的打包和分发机制。云上部署的 Cloud Foundry 会为大部分编程语言定义一种打包的格式,当开发人员执行命令的时候,实际上是将可执行文件和启动脚本打包上传到云上的Coulud Foudry 中,然后 Cloud Foundry 通过相应的调度器选择一个虚拟机的 Agent 将压缩包下载后启动
虚拟机一般不可能只跑一个应用,因为这样确实也太浪费资源了,我们可以想想,现在手上的电脑,可以用 Vmvare 导入几个虚拟机,所以诸如 Cloud Foundry 通过引入操作系统的 Cgroups 和 Namespace 等机制,从而来为每个应用单独创建一个叫做「沙盒」的隔离环境,然后在这些「沙盒」中启动应用,通过这样的方法就让虚拟机中应用各自互不干扰,让其自由翱翔,至于 Cgroups 和 Namespace 的实现原理,后续我们再共同的探讨 这里所谓的隔离环境就是「容器」。
自然不一样,不然现在我们一旦提到容器,想到的不会是 Docker,而是 Cloud Foundry 了吧。Cloud Foundry 的首席产品经理就觉得没什么,毕竟自己放的屁都是香的! 不一样,而且当时还发了一份报告,报告中还写到:“ Docker 不就是使用了 Cgroups 和 Namespace 实现的「沙盒」而已,不用过于关注”。 没想到的是,随后短短的几个月,Docker 项目迅速起飞以至于其他所有 Paas 社区都还没来及反应过来,就已经宣告出局
就是提出了镜像的概念。上面我们说过,Paas 提供的一套应用打包的功能,看起很轻松省事,但是一旦使用了Paas,你就要终身服务于它,毕竟他是提供商,是「爸爸」,用户需要为每个版本,每种语言去维护一个包,这个打包的过程是需要多次的尝试,多次试错后,才能摸清本地应用和远端 Paas 的脾气,从而顺利部署。 而 Docker 镜像恰恰就是解决了打包这一根本问题。
Docker 镜像也是一个压缩包,只是这个压缩包不只是可执行文件,环境部署脚本,它还包含了完整的操作系统。因为大部分的镜像都是基于某个操作系统来构建,所以很轻松的就可以构建本地和远端一样的环境。 这就很牛皮了,如果我们的应用是在 Centos7 上部署,我们只需要将项目环境部署在基于 Centos7 的环境中,然后无论在哪里去解压这个压缩包,都可以保证环境的一致性。在整个过程中,我们根本不需要进行任何的配置,因为这个压缩包可以保证:本地的环境和云端是一致的,这也是 Docker 镜像的精髓 开发者体验到了 Docker 的便利,从而很快宣布 Paas 时代的结束,不过对于大规模应用的部署,Docker 能否实现在当时还是个问号 就在 2014 年的 DockerCon 上,紧接着发布了自研的「Docker swarm」,Docker 就这样 一度奔向高潮,即将就到达了自己梦想之巅。
虽然 Docker 通过「容器」完成了对 Paas 的「降维打击」,但是 Docker 的目的是:如何让更多的开发者将项目部署在自己的项目上,从技术,商业,市场多方位的争取开发者的群体,为此形成自家的 Paas 平台做铺垫 Docker 项目虽然很受欢迎,就目前看来只是一个创建和启动容器的小工具。需要应该清楚的一点是,用户最终部署的还是他们的网站,服务甚至云计算业务。所以推出一个完整的整体对外提供集群管理功能的 Swarm 势在必行,这个项目中的最大亮点即直接使用了 Docker 原生的 API 来完成对集群的管理。 对于单机项目,只需要执行下面一条语句即可实现容器 对于多机的项目,只需要执行 你看,从单机切换到多机,使用的方法也就参数不同而已,所以这样一个原生的「Docker容器集群管理」一发布就受到大家的青睐。随着自身生态的逐渐完善,借助这一波浪潮并通过各种并购来强大自己的平层能力 要说最成功的案例,非 Fig 项目莫属。之所以这么屌,是因为作者提出了「容器编排」的概念。
其实这也不是什么新鲜内容,比如在 Linux 中的 Makefile和常见的 SHELL 脚本,它是一种通过工具或者配置来完成一组虚拟机或者关联资源的定义、配置、创建等工具。
我们先以 Fig 为例,假设开发人员小黑,现在要部署一个项目,其中包含了应用容器 A,数据库容器 B,负载容器 C,这个时候 Fig 只需要将三个容器定义在一个配置文件,然后指定他们的关联关系,执行下面的命令即可 当然也可以在 Fig 的配置文件中配置各种容器的副本,然后加上 Swarm 的集群管理功能,这样不就是 Paas 了么。只是这个项目被收购以后,修改名字为 compose 了,后续也会的 compose 进行详细的阐述 就这样一个以「鲸鱼」为商标的 Docker,火遍全球,因为它秉持将「开发者」群体放在食物链的顶端。一分钟实现网站的部署,三分钟搭建集群,这么多年以来,很多后端开发者很少将眼光放在 Linux 技术上,开发者们为了深入的了解 Docker 的技术原理,终于将眼光放入诸如 Cgroups 和 Namespace 技术中。 就在这一时之间,后端及云计算领域的大佬都汇聚于这个「小鲸鱼」的身边。随后到了考虑集群的方案,论集群的管理调度能力,还不得不提 Berkeley 的 Mesos,专注于大数据领域,更加关注的是计算密集型的业务。凭借着它天生的两层调度机制,让它很快发布了一个叫做 Marathon 的项目,这个项目随即成为了 Swarm 的有力竞争对手。 这还没完,说了这么久,还没有提到在基础设施领域翘楚的 Google 公司,是的,同在这一年,宣告了一个叫做 Kubernetes 项目的诞生。 随着 Docker 生态的建立,Docker swarm,Docker compose,Machine 形成了三件套,此时大量围绕Docker 项目的网络,存储,监控都涌现。在令人兴奋的背后,是对它更多的担忧,这主要来源于对 Docker 商业化战略的顾虑,Docker 公司对于 Docker 着绝对的权威并在多个场合直接和谷歌,微软对干 其实在 Docker 兴起的时候,谷歌也开源了一个 Linux 容器:Imctfy,在当时这个项目在 Docker 面前真是弟弟,所以向 Docker 公司表示想合作的意愿,Docker 显然不同意,且在之后的不久自己发布了一个容器运行时的库 Libcontainer,可能由于太急躁,其代码可读性极差,不稳定和频繁的变更,让社区叫苦不迭 为了切割 Docker 项目的话语权,决定成立一个中立的基金会。所以于 2015 年将这个 Libcontainer 捐出,并修改名称为 Runc,然后依据 RunC 项目,制定了一套容器和镜像的标准和规范----OCI
为了让 Docker 不能太嚣张,其他玩家构建自身平台的时候不依赖于 Docker 项目,提出一个标准和规范----OCI。这一标准并没有改变 Docker 在容器领域一家独大的现状。Google 坐不住了,必须得搞点大招 **Google **给 RedHat 等伙伴打了电话,说咱们共同牵头发起一个基金会-----CNCF。目的很简单,以 kubernetes 为基础,建立一个以由开源基础设置主导,按照独立基金会方式运营的平台级社区,来对抗 Docker 公司为核心的容器商业生态 为了做好这个事儿,CNCF 必须完成两件事儿
Swarm 的无缝集成以及 Mesos 的大规模集群的调度管理能力,很明显,如果继续往这两个方向发展,后面的路不一定好走。所以,kubernetes 选择的方式是 Borg,其基础特性是 Google 在容器化基础设施多年来实践的经验,这也正是项目从一开始就避免了和 Swarm ,mesos 社区同质化的重要手段
RedHat 正好擅长这玩意呀,它能真正的理解开源社区运作和项目研发真谛的合作伙伴。作为 Docker 一方,主要不管的强调「Docker native」,但是由于 kubernetes 没有跟 Swarm 展开同质化的竞争,所以这个「Docker Native」的说法并没有什么杀伤力。反而其独特的设计理念和号召力,让其构建了一个完全与众不同的容器编排管理生态。 就这样很快就把 Swarm 甩在了身后。随机开始探讨第二个问题,CNCF 添加了一系列容器工具和项目,面对这样的压迫,Docker 在2016年决定放弃现有的 Swarm项目,而是将容器编排等全部内置到 Docker 项目中。 而 kubunetes 的应对方案也蛮有意思,开启「民主化架构」,kubernetes 为开发者暴露可以扩展的插件机制,让用户可以随意的通过植入代码的方式介入到 kubernetes 的每一个阶段,很快,整个容器圈出现了优秀的作品:火热的微服务治理项目 lstio 等 面对 kubernetes 的 强力攻击,Docker 公司不得不面对失败的事实,只好放弃开源社区专注于商业化转型,所以于2017年将容器运行时部分 containerd 捐赠给了 CNCF,从而将 Docker 项目改名为 Moby,然后交给社区维护,于 2017 年,**Docker **公司宣布将在企业版内置 kubernetes 项目,这也标志了 kubernetes「编排之争」的结束 Docker能做什么Docker 是一个用于开发,发布,运行应用的程序于一体的开放平台。如果我们需要将货物整齐的摆放在船上且互不影响,那么一种可行的方案即通过集装箱进行标准化,我们将各种货品通过集装箱打包,然后统一的放在船上进行运输,Docker其实就是这样一个将各种软件进行打包成集装箱,然后分发。 Docker的安装Docker 是一个跨平台的解决方案,支持各大平台比如 Centos,Ubuntu等 Linux 发行版。下面讲述的是在Centos 中的使用,安装
运行上述命令,Docker 首先会检查本地是否有 hello-world 这个镜像,如果发现本地没有这个镜像,Docker 就会去 Docker Hub 官方仓库下载此镜像,然后运行它。最后我们看到该镜像输出 'Hello from Docker!' 并退出。 Docker核心概念Docker 的操作主要围绕镜像,容器,仓库三大核心概念
一句话说即镜像是 Docker 容器启动的先决条件,因为镜像会提供容器运行的一些基础文件和配置文件,是容器启动的基础。说白了,要启动容器,需要镜像来提供一些基础环境。
容器是镜像的运行实体。镜像是静态的只读文件,可是容器是要运行的,需要可写文件层。所以容器运行着真正的应用进程,所以自然会有创建,运行,停止,暂停和删除五种状态 既然容器是直接运行的运行程序,那它是有自己的命名空间嘛? 容器有自己独立的命名空间和资源限制,意味着在容器内部,你无法看到主机上面的进程,环境变量等信息,这就是容器和物理机上的进程本质区别
镜像仓库类似于代码仓库,用来分发和存储镜像,分为公共镜像和私有镜像。Docker hub 是 Docker 的官方公开镜像仓库,很多的官方镜像都可以在上面找到,但是访问很慢,所以可以找国内的镜像源,当然后面我们也会自己搭建一个私有镜像仓库
上图清晰的展现了镜像是容器的基石,容器是在镜像的基础上创建的。一个镜像可以创建多个容器,仓库用来存放和分发镜像 Docker架构容器技术的发展可说突飞猛进了,市面上除了 Docker 容器还有 coreos 的 rkt,lxc 等,这么多种容器,是不是需要一个标准呢,不然就太容易乱套了 你可能会说直接把 Docker 作为标准不就好了,但是有这么多相关的容器技术,谁不想吃个好瓜,除此之外,当时的编排的技术也竞争火爆,当时的三主力分别是 Docker Swarm,kubernetes 以及 mesos。作为原生的 Docker Swarm 自然优势明显,但是 kubernetes 不同意啊,它们觉得调度形式太单一了 因此爆发了容器大战,OCI 也就在此出现。 OCI 是开放的容器标准,轻量级开放的治理结构,目前主要有两个标准,分别是容器运行时标准和容器镜像标准 在如此竞争激烈下面,Docker 的架构成为了下面这个样子 Docker 的整体架构为 CS 架构,客户端和服务端两部分组成,客户端发送命令,服务端接受处理指令,其通信的方式有多种,即可以通过 Unix 套接字通信,也可以网络链接远程通信 Docker客户端 我们平时通常使用 Docker 命令行的方式和服务端打交道,其实还可以通过 **REST API **的方式和 Docker 服务端交互,甚至使用各种预言的 sdk 和 Docker 的服务端交互,美滋滋 Docker服务端 Docker 服务端是 Docker 后台服务的总称。其中 Dockerd 是一个非常重要的后台进程,它负责响应并处理Docker 客户端的请求,然后转化为 Docker 的具体操作 Docker 重要的组件 我们去 Docker 默认安装路径先看看有哪些组件 这里主要说明下 runc 和 contained 组件
通过上图,可以看到,dockerd 通过 gRPC 与 containerd 通信,由于 dockerd 与真正的容器运行时,runC 中间有了 containerd 这一 OCI 标准层,使得 dockerd 可以确保接口向下兼容。 gRPC 是一种远程服务调用。containerd-shim 的意思是垫片,类似于拧螺丝时夹在螺丝和螺母之间的垫片。containerd-shim 的主要作用是将 containerd 和真正的容器进程解耦,使用 containerd-shim 作为容器进程的父进程,从而实现重启 dockerd 不影响已经启动的容器进程。
此时发现其 pid 为 4428,随后我们查看进程之间的关系
注意,docker19 就看不到两者是父子关系了 可以先使用 ps aux | grep contained ,然后使用 pstree 查看 contained 的 pid ,实际上,Docker 启动的时候,contained 就启动了,dockerd 和 contained 一直就存在。当执行了docker run以后,contained 就会创建 contained-shim 充当垫片进程,然后启动容器的真正进程 sleep 3600,这和架构图一致 075528566666 Docker相关组件
对于我们最直观的即 Docker 命令,作为 Docker 客户端的完整实现,通过 Docker 命令来实现所有的 Docker 客户与服务端的通信
Docker 组件向服务端发送请求后,服务端根据请求执行具体的动作并将结果返回给 Docker,Docker 解析服务端的返回结果,并将结果通过命令行标准输出展示给用户。这样一次完整的客户端服务端请求就完成了
dockerd 为 Docker 服务端后台的常驻进程,负责接收客户端的请求,处理具体的任务并将结果返回客户端
第一种方式:通过 unix 套接字与服务端通信,配置的格式为: 第二种方式:采用 TCP 的方式与服务端通信,配置格式为: 第三种方式:通过 fd 文件描述符的方式,配置格式为:fd://这种格式一般用于 systemd 管理的系统中。
在 Linux 中,有一个叫做 init 的进程,是所有进程的父进程,用来回收那些没有回收的进程,同样的道理,在容器内部,可以通过加上参数
此时的 1 号进程为为 sh 进程,如果加上 --init 你会发现,此时的 1 号进程为 docker-init,而不是 sh 了
docker-proxy 用来将容器启动的端口映射到主机,方便主机的访问。 假设目前启动一个 nginx 容器并将容器的 80 端口映射到主机的 8080 端口 查看容器 IP 此时使用 ps 查看主机是否有 docker-proxy 进程 可以发现当进行端口映射的时候,docker 为我们创建了一个 docker-proxy 进程,并且通过参数将容器的 IP 和端口传递给 docker-proxy,然后 proxy 通过 iptables 完成 nat 的转发 从最后一句可以看出,当我们主机访问 8080 端口的时候,iptable 将流量会转发给 使用 curl 访问一下 nginx 容器 contained组件
contained主要负责容器的生命周期管理,同时还会负责一些其他的功能
镜像的管理 接收dockerd的请求 管理存储相关资源 管理网络资源
Docker镜像使用来,继续,我们看看镜像是什么。镜像是一个只读的镜像模版且包含了启动容器所需要的文件结构内容。镜像不包含动态数据,构建完成将不会改变
对于镜像的操作分为:
拉取镜像直接使用 docker pull 命令即可,命令的格式如下
现在举个例子,这里有个镜像叫做 busybox,这个镜像集成了上百个常用的 Linux 命令,可以通过这个镜像方便快捷的查找生产环境中的问题,下面我们一起操作一波
首先会在本地镜像库查找,如果不存在本地库则直接去官网拉取镜像。拉取完镜像后随即查看镜像
如果要查看指定的镜像,则使用docker image ls命令进一步查询
我们仔细观察这两个镜像,就会发现这两个镜像的 IMAGE ID其实是一样的,这是什么原因呢 实际上他们都是指向的同一个镜像文件,只不过其别名不一样而已,如果此时不想要mybox镜像,想删除这个镜像
此时再次使用 docker images 查看确实删除了
之前说过,有两种方式,一种是通过 docker commit 的方式,一种是 docker build 的方式。首先看看使用容器提交镜像的方式 此时启动了一个busybox容器并进入到容器,并在容器中创建一个文件,并写入内容 此时就在当前目录下创建了一个hello.txt文件并写入了内容。现在新建另外一个窗口,然后提交为一个镜像 然后使用 docker image ls 查看发现确实生成了镜像 然后我们再看看使用 dockerfile 的方式
先看看都有哪些命令 这么多,不存在的,我们先看一个dockerfile就知道如何用了
为了清楚的看见镜像的存储结构,通过 因为我的 可以清楚的看到, Docker容器操作我们通过一个镜像可以轻松的创建一个容器,一个镜像可以有多个容器,在运行容器的时候,实际上是在容器内部创建了这个文件系统的读写副本,如下图所示
容器的生命周期一共有五个状态分别为
通过 docker cretate 进入容器的初建状态,然后通过 docker start 进入运行状态,通过 docker stop 进入停止状态,运行状态的容器可以通过 docker pause 让其变为暂停状态,为了详细的查看这些过程,我们实操一下
通过 docker create 创建的容器处于停止的状态,使用 docker start busybox 进入启动状态 当使用 docker run 创建并启动容器的时候,docker 后台的执行逻辑为
同时使用 通过 docker stop 停止容器,其原理是给运行中的容器给
想要进入容器,有三种方案,分别是
通过 可是当我们在进行窗口进行 docker attach 的时候,这个命令就不好用了,所以使用 docker exec 的方式
奇怪的发现居然是两个
现在基本上知道了如何创建,启动容器,那么怎么删除容器呢
如果此时,容器正在运行,那么需要添加
这简单,不过在导出之前先进入容器创建一个文件 然后导出为文件 此时会在当前目录生成一个
通过 此时容器名称为 此时发现之前在 仓库容器的基本操作应该都会了,那么我们应该如何去存储和分发这些镜像,这就需要介绍下仓库; 我们可以使用共有镜像仓库分发,也可以搭建私有的仓库
钱钱仓库放钱,这个仓库放镜像。 在学习的过程中,不太能区分注册服务器和仓库的关系。注册服务器其实是用来存放仓库的实际机器,而仓库我们可以将其理解为具体的项目或者目录。一个注册服务器可以存放多个仓库,每个仓库可以存放多个镜像
Docker hub 是当前全球最大的镜像市场,差不多超过 10w 个容器镜像,大部分操作系统镜像都来自于此。
此时假设我的账户是 xiaolantest,创建一个 busybox 的仓库,随后将镜像推送到仓库中。 第一步:拉取 busybox 镜像 第二步:推送镜像之前先登录镜像服务器(注意用户名密码哦),出现 login Succeeded表示登录成功 第三步:推送之前还要做一件事,重新对镜像命名,这样测能正确的推动到自己创建的仓库中 第四步:docker push 到仓库中
Docker 官方提供了开源的镜像仓库 Distribution,镜像存放于 Docker hub 的 Registry中
此时 Docker 为
此时,我们验证一下从本地镜像仓库拉取镜像。首先,我们删除本地的
可以看到此时本地已经没有 随后再使用 总结不知不觉,每周下班开始写,做实验,截图,至此也就告一段落了,开篇思维导图由于完整版太大,我计划一共分为四篇文章,分别为 Docker 基本认识,Docker 实战,Docker 底层原理以及Docker 集群安全四个方面来分享,后续精简后再给大家。本篇文章从 Docker 容器圈到基本使用,写的应该蛮清楚了,另外说明一下,由于直接使用代码很可能导致格式排版混乱,所以全部采用截图的方式,更加直观和清晰,当然如有不妥之处也望大家指正。点赞,转发,收藏,感谢!我们下期见! 暖蓝笔记 解锁面试的点点滴滴,一起向上成长! 20篇原创内容 公众号 |
|
来自: wenxuefeng360 > 《大数据》