0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

关于Docker的基础

Linux爱好者 来源:Linux爱好者 作者:Linux爱好者 2021-03-31 17:16 次阅读

这周分享的内容是关于 Docker 的基础,大概的内容分为下面的两个部分,另外还做了个视频,其实这个视频仅仅用来娱乐娱乐而已。

前言

第一趴---Docker容器圈简介

34fb6fb0-8d80-11eb-8b86-12bb97331649.png

Docker容器圈简介

第二趴---Docker基本操作

3536bb88-8d80-11eb-8b86-12bb97331649.png

Docker基本操作

容器圈

容器这个新生事物,现在还可以说是新生事物吗?对于我们学生而言,我觉得没毛病,你说呢?

容器技术可说重塑了整个云计算市场的形态,带动了一批年轻有为的容器技术儿,不过「容器」这个概念是Docker公司发明的么,不是,它只是众多Paas项目中的最底层,没人关注的那一部分而已。

什么是Pass项目?

Paas项目之所会被很多公司所接受,自然是因为解放了部分开发人员的劳动力,尽快干玩活儿早点下班。其依赖的就是「应用托管」的能力,在电脑上斗过地主的应该知道,托管了以后就会自动出牌,同样的道理,为了尽量的弥补本地和云上的环境差异,就出现了Paas开源项目。

举个例子来说,运维人员小仙云上部署一个Cloud Foundry项目,开发人员只需要简单的一行代码就可以实现将本地的应用部署到云上

3592dad0-8d80-11eb-8b86-12bb97331649.png

就这样一行代码就实现了将本地应用上传到云上,属实很轻松。

那么这个命令执行的基本原理是怎样的?

实际上,我们可以将其最核心的组件理解为一套应用的打包和分发机制。云上部署的Cloud Foundry会为大部分编程语言定义一种打包的格式,当开发人员执行命令的时候,实际上是将可执行文件和启动脚本打包上传到云上的Coulud Foudry中,然后Cloud Foundry通过相应的调度器选择一个虚拟机的Agent将压缩包下载后启动

那如何区分虚拟机中的不同应用呢?

虚拟机一般不可能只跑一个应用,因为这样确实也太浪费资源了,我们可以想想,现在手上的电脑,可以用Vmvare导入几个虚拟机,所以诸如Cloud Foundry通过引入操作系统的Cgroups和Namespace等机制,从而来为每个应用单独创建一个叫做「沙盒」的隔离环境,然后在这些「沙盒」中启动应用,通过这样的方法就让虚拟机中应用各自互不干扰,让其自由翱翔,至于Cgroups和 Namespace 的实现原理,后续我们再共同的探讨

这里所谓的隔离环境就是「容器」。

那 Docker 和这 Pass 项目的 Cloud Foundry 的容器有啥不一样?

自然不一样,不然现在我们一旦提到容器,想到的不会是Docker,而是Cloud Foundry了吧。Cloud Foundry的首席产品经理就觉得没什么,毕竟自己放的屁都是香的!

不一样,而且当时还发了一份报告,报告中还写到:“Docker不就是使用了 Cgroups和 Namespace实现的「沙盒」而已,不用过于关注”。

没想到的是,随后短短的几个月,Docker项目迅速起飞以至于其他所有 Paas社区都还没来及反应过来,就已经宣告出局

什么魔力让 Docker 一发不可收拾?

就是提出了镜像的概念。上面我们说过,Paas提供的一套应用打包的功能,看起很轻松省事,但是一旦使用了Paas,你就要终身服务于它,毕竟他是提供商,是「爸爸」,用户需要为每个版本,每种语言去维护一个包,这个打包的过程是需要多次的尝试,多次试错后,才能摸清本地应用和远端Paas的脾气,从而顺利部署。

而Docker 镜像恰恰就是解决了打包这一根本问题。

什么是Docker镜像?

Docker镜像也是一个压缩包,只是这个压缩包不只是可执行文件,环境部署脚本,它还包含了完整的操作系统。因为大部分的镜像都是基于某个操作系统来构建,所以很轻松的就可以构建本地和远端一样的环境。

这就很牛皮了,如果我们的应用是在Centos7上部署,我们只需要将项目环境部署在基于Centos7的环境中,然后无论在哪里去解压这个压缩包,都可以保证环境的一致性。在整个过程中,我们根本不需要进行任何的配置,因为这个压缩包可以保证:本地的环境和云端是一致的,这也是Docker镜像的精髓

开发者体验到了Docker的便利,从而很快宣布Paas时代的结束,不过对于大规模应用的部署,Docker能否实现在当时还是个问号

就在 2014 年的DockerCon上,紧接着发布了自研的「Docker swarm」,Docker就这样 一度奔向高潮,即将就到达了自己梦想之巅。

为什么会推出Docker Swarm?

虽然Docker通过「容器」完成了对Paas的「降维打击」,但是Docker的目的是:如何让更多的开发者将项目部署在自己的项目上,从技术,商业,市场多方位的争取开发者的群体,为此形成自家的 Paas平台做铺垫

Docker项目虽然很受欢迎,就目前看来只是一个创建和启动容器的小工具。需要应该清楚的一点是,用户最终部署的还是他们的网站,服务甚至云计算业务。所以推出一个完整的整体对外提供集群管理功能的Swarm势在必行,这个项目中的最大亮点即直接使用了Docker原生的API来完成对集群的管理。

对于单机项目,只需要执行下面一条语句即可实现容器

35d209bc-8d80-11eb-8b86-12bb97331649.png

对于多机的项目,只需要执行

35e8c044-8d80-11eb-8b86-12bb97331649.png

你看,从单机切换到多机,使用的方法也就参数不同而已,所以这样一个原生的「Docker容器集群管理」一发布就受到大家的青睐。随着自身生态的逐渐完善,借助这一波浪潮并通过各种并购来强大自己的平层能力

要说最成功的案例,非Fig项目莫属。之所以这么屌,是因为作者提出了「容器编排」的概念。

什么是容器编排?

其实这也不是什么新鲜内容,比如在Linux中的Makefile和常见的SHELL脚本,它是一种通过工具或者配置来完成一组虚拟机或者关联资源的定义、配置、创建等工具。

容器的编排是怎么样的呢

我们先以 Fig 为例,假设开发人员小黑,现在要部署一个项目,其中包含了应用容器A,数据库容器B,负载容器C,这个时候Fig只需要将三个容器定义在一个配置文件,然后指定他们的关联关系,执行下面的命令即可

360c8d3a-8d80-11eb-8b86-12bb97331649.png

当然也可以在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

什么是OCI

为了让Docker不能太嚣张,其他玩家构建自身平台的时候不依赖于Docker项目,提出一个标准和规范----OCI。这一标准并没有改变 Docker 在容器领域一家独大的现状。Google 坐不住了,必须得搞点大招

**Google **给RedHat等伙伴打了电话,说咱们共同牵头发起一个基金会-----CNCF。目的很简单,以kubernetes为基础,建立一个以由开源基础设置主导,按照独立基金会方式运营的平台级社区,来对抗Docker公司为核心的容器商业生态

为了做好这个事儿,CNCF 必须完成两件事儿

必须在编排领取足够的优势

CNCF 必须以 kubernetes 为核心,覆盖更多的场景

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,执行下面的命令

362f44f6-8d80-11eb-8b86-12bb97331649.png

添加Docker安装源

36517828-8d80-11eb-8b86-12bb97331649.png

安装最新版

3682d81e-8d80-11eb-8b86-12bb97331649.png

如果需要安装指定版本,可以通过下面命令查看版本并选择需要的版本

369a1e20-8d80-11eb-8b86-12bb97331649.png

安装完成,启动Docker

36cc4ce2-8d80-11eb-8b86-12bb97331649.png

按照国际案例,先跑一个 helloworld

36e33ab0-8d80-11eb-8b86-12bb97331649.png

运行上述命令,Docker首先会检查本地是否有hello-world这个镜像,如果发现本地没有这个镜像,Docker就会去Docker Hub官方仓库下载此镜像,然后运行它。最后我们看到该镜像输出 "Hello from Docker!" 并退出。

Docker核心概念

Docker的操作主要围绕镜像,容器,仓库三大核心概念

什么是镜像?

一句话说即镜像是Docker容器启动的先决条件,因为镜像会提供容器运行的一些基础文件和配置文件,是容器启动的基础。说白了,要启动容器,需要镜像来提供一些基础环境。

使用的镜像的方式有哪些?

自定义创建镜像。首先找一个基础镜像,比如此镜像是Centos,然后在此镜像基础上自定义需要的内容。举个例子,基础镜像为Centos,先安装Nginx服务,然后部署咱们的应用程序,最后做一些自定义的配置,这样一个镜像就完成了,此镜像的操作系统是Centos,其中包含了Nginx服务

从仓库寻找别人已经做好的镜像。直接去 **Docker hub **或者其他公开仓库 下载即可

什么是容器?

容器是镜像的运行实体。镜像是静态的只读文件,可是容器是要运行的,需要可写文件层。所以容器运行着真正的应用进程,所以自然会有创建,运行,停止,暂停和删除五种状态

既然容器是直接运行的运行程序,那它是有自己的命名空间嘛?

容器有自己独立的命名空间和资源限制,意味着在容器内部,你无法看到主机上面的进程,环境变量等信息,这就是容器和物理机上的进程本质区别

什么是仓库?

镜像仓库类似于代码仓库,用来分发和存储镜像,分为公共镜像和私有镜像。Docker hub是Docker的官方公开镜像仓库,很多的官方镜像都可以在上面找到,但是访问很慢,所以可以找国内的镜像源,当然后面我们也会自己搭建一个私有镜像仓库

三者的关系是怎么样的?

36fea52a-8d80-11eb-8b86-12bb97331649.png

上图清晰的展现了镜像是容器的基石,容器是在镜像的基础上创建的。一个镜像可以创建多个容器,仓库用来存放和分发镜像

Docker架构

容器技术的发展可说突飞猛进了,市面上除了Docker容器还有coreos的 rkt,lxc 等,这么多种容器,是不是需要一个标准呢,不然就太容易乱套了

你可能会说直接把Docker作为标准不就好了,但是有这么多相关的容器技术,谁不想吃个好瓜,除此之外,当时的编排的技术也竞争火爆,当时的三主力分别是Docker Swarm,kubernetes以及mesos。作为原生的Docker Swarm自然优势明显,但是kubernetes不同意啊,它们觉得调度形式太单一了

因此爆发了容器大战,OCI也就在此出现。

OCI是开放的容器标准,轻量级开放的治理结构,目前主要有两个标准,分别是容器运行时标准和容器镜像标准

在如此竞争激烈下面,Docker的架构成为了下面这个样子

3727a42a-8d80-11eb-8b86-12bb97331649.png

Docker的整体架构为CS架构,客户端和服务端两部分组成,客户端发送命令,服务端接受处理指令,其通信的方式有多种,即可以通过Unix套接字通信,也可以网络链接远程通信

Docker客户端

我们平时通常使用Docker命令行的方式和服务端打交道,其实还可以通过 **REST API **的方式和Docker服务端交互,甚至使用各种预言的sdk和Docker的服务端交互,美滋滋

Docker服务端

Docker服务端是 Docker 后台服务的总称。其中Dockerd是一个非常重要的后台进程,它负责响应并处理Docker客户端的请求,然后转化为Docker的具体操作

Docker 重要的组件

我们去 Docker 默认安装路径先看看有哪些组件

3758d9a0-8d80-11eb-8b86-12bb97331649.png

这里主要说明下runc和contained组件

runc:是一个用来运行容器的轻量级工具

contained:是容器标准化后的产物,从Dockerd剥离出来,contained通过contained-shim启动并管理runc,可以说contained是真正管理容器的生命周期

3786caa4-8d80-11eb-8b86-12bb97331649.png

通过上图,可以看到,dockerd通过gRPC与containerd通信,由于dockerd与真正的容器运行时,runC中间有了containerd这一 OCI标准层,使得dockerd可以确保接口向下兼容。

gRPC是一种远程服务调用。containerd-shim的意思是垫片,类似于拧螺丝时夹在螺丝和螺母之间的垫片。containerd-shim的主要作用是将containerd和真正的容器进程解耦,使用containerd-shim作为容器进程的父进程,从而实现重启dockerd不影响已经启动的容器进程。

docker 各个组件之间的关系

启动一个容器

37b1e108-8d80-11eb-8b86-12bb97331649.png

启动完成,通过下面命令查看 docker 的 pid

37da8ad6-8d80-11eb-8b86-12bb97331649.png

此时发现其 pid 为 4428,随后我们查看进程之间的关系

通过 pstree 查看进程之间的关系

37f2e9be-8d80-11eb-8b86-12bb97331649.png

注意,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组件向服务端发送请求后,服务端根据请求执行具体的动作并将结果返回给Docker,Docker解析服务端的返回结果,并将结果通过命令行标准输出展示给用户。这样一次完整的客户端服务端请求就完成了

dockerd

dockerd 为Docker服务端后台的常驻进程,负责接收客户端的请求,处理具体的任务并将结果返回客户端

那么 Docke r客户端采用哪几种方式发送请求

第一种方式:通过unix套接字与服务端通信,配置的格式为:unix://socket_path。默认的dockerd生成的 socket文件存放在 /var/run/docker.sock,此文件只能是root用户才能访问,这也是为什么刚安装完Docker后只能root 来进行访问操作

第二种方式:采用TCP的方式与服务端通信,配置格式为:tcp://host:por,为了保证安全,通常还需要使用TLS认证

第三种方式:通过fd文件描述符的方式,配置格式为:fd://这种格式一般用于systemd管理的系统中。

docker-init

在Linux中,有一个叫做init的进程,是所有进程的父进程,用来回收那些没有回收的进程,同样的道理,在容器内部,可以通过加上参数 --init 的方式,让 1 号进程管理所有的子进程,例如回收僵尸进程

举个例子示范,以镜像 busybox 为例

382b67b2-8d80-11eb-8b86-12bb97331649.png

此时的 1 号进程为为 sh 进程,如果加上 --init

384c2164-8d80-11eb-8b86-12bb97331649.png

你会发现,此时的 1 号进程为docker-init,而不是sh了

docker-proxy

docker-proxy 用来将容器启动的端口映射到主机,方便主机的访问。

假设目前启动一个nginx容器并将容器的80端口映射到主机的8080端口

3871cb3a-8d80-11eb-8b86-12bb97331649.png

查看容器 IP

38893e1e-8d80-11eb-8b86-12bb97331649.png

此时使用 ps 查看主机是否有 docker-proxy 进程

38aba7ce-8d80-11eb-8b86-12bb97331649.png

可以发现当进行端口映射的时候,docker为我们创建了一个docker-proxy进程,并且通过参数将容器的IP和端口传递给docker-proxy,然后proxy通过iptables完成nat的转发

38c7a2f8-8d80-11eb-8b86-12bb97331649.png

从最后一句可以看出,当我们主机访问 8080 端口的时候,iptable将流量会转发给 172.17.0.2 的 80 ,从而实现主机上直接访问容器的业务

使用curl访问一下nginx容器

38e3d900-8d80-11eb-8b86-12bb97331649.png

contained组件

containerd

contained主要负责容器的生命周期管理,同时还会负责一些其他的功能

主要负责那些功能?

镜像的管理

接收dockerd的请求

管理存储相关资源

管理网络资源

containerd-shim

containerd-shim 的意思是垫片,类似于拧螺丝时夹在螺丝和螺母之间的垫片。containerd-shim 的主要作用是将 containerd 和真正的容器进程解耦,使用 containerd-shim 作为容器进程的父进程,从而实现重启 containerd 不影响已经启动的容器进程。

ctr

ctr 实际上是 containerd-ctr,它是 containerd 的客户端,主要用来开发和调试,在没有 dockerd 的环境中,ctr 可以充当 docker 客户端的部分角色,直接向 containerd 守护进程发送操作容器的请求。

Docker镜像使用

来,继续,我们看看镜像是什么。镜像是一个只读的镜像模版且包含了启动容器所需要的文件结构内容。镜像不包含动态数据,构建完成将不会改变

对于镜像都有哪些操作?

39025b64-8d80-11eb-8b86-12bb97331649.png

对于镜像的操作分为:

拉取镜像:通过docker pull拉取远程仓库的镜像

重命名镜像:通过docker tag重命名镜像

查看镜像:通过docker image ls查看本地已经存在的镜像

删除镜像:通过docekr rmi删除没有用的镜像

构建镜像

第一种是通过docker build命令基于dockerfile构建镜像,推荐

第二种是通过docker commit基于运行的容器提交为镜像

拉取镜像

拉取镜像直接使用 docker pull 命令即可,命令的格式如下

39645670-8d80-11eb-8b86-12bb97331649.png

registry为注册的服务器,docker 默认会从官网docker.io上拉取镜像,当然可以将registry注册为自己的服务器

repository为镜像仓库,library为默认的镜像仓库

image为镜像的名称

tag为给镜像打的标签

现在举个例子,这里有个镜像叫做busybox,这个镜像集成了上百个常用的Linux命令,可以通过这个镜像方便快捷的查找生产环境中的问题,下面我们一起操作一波

docker pull busybox

首先会在本地镜像库查找,如果不存在本地库则直接去官网拉取镜像。拉取完镜像后随即查看镜像

查看镜像---docker images

如果要查看指定的镜像,则使用docker image ls命令进一步查询

重命名镜像采用打标签的方式重命名,格式如下

3987946e-8d80-11eb-8b86-12bb97331649.png

我们仔细观察这两个镜像,就会发现这两个镜像的 IMAGE ID其实是一样的,这是什么原因呢

实际上他们都是指向的同一个镜像文件,只不过其别名不一样而已,如果此时不想要mybox镜像,想删除这个镜像

使用 docker rmi 删除镜像

此时再次使用 docker images 查看确实删除了

如何自己构建自己镜像呢

之前说过,有两种方式,一种是通过docker commit的方式,一种是docker build的方式。首先看看使用容器提交镜像的方式

39b14764-8d80-11eb-8b86-12bb97331649.png

此时启动了一个busybox容器并进入到容器,并在容器中创建一个文件,并写入内容

39c8e4aa-8d80-11eb-8b86-12bb97331649.png

此时就在当前目录下创建了一个hello.txt文件并写入了内容。现在新建另外一个窗口,然后提交为一个镜像

39eb1b10-8d80-11eb-8b86-12bb97331649.png

然后使用 docker image ls 查看发现确实生成了镜像

然后我们再看看使用 dockerfile 的方式

dockerfile的每一行的命令都会生成独立的镜像层并拥有唯一的id

dockerfile命令是完全透明的,通过查看dockerfile的内容,就可以知道镜像是怎么一步步构建的

dockerfile为纯文本,方便做版本控制

先看看都有哪些命令

3a0d60e4-8d80-11eb-8b86-12bb97331649.png

这么多,不存在的,我们先看一个dockerfile就知道如何用了

3af887a4-8d80-11eb-8b86-12bb97331649.png

首先第一行表示基于什么镜像构建

第二行是拷贝文件nginx。repo 到容器内的 /etc/yum.repos.d

第三行为容器中运行 yum install 命令,安装 nginx 命令到容器

第四行为生命容器使用 80 端口对外开放

第五行定义容器启动时的环境变量HOST=mynginx,容器启动后可以获取到环境变量 HOST 的值为 mynginx。

第六行定义容器的启动命令,命令格式为json 数组。这里设置了容器的启动命令为 nginx ,并且添加了 nginx 的启动参数 -g 'daemon off;' ,使得 nginx 以前台的方式启动。

基本操作已经会了,现在我们看看镜像的实现原理

3b15e63c-8d80-11eb-8b86-12bb97331649.png

第一行:创建一个 busybox 镜像层

第二行:拷贝本机 test 文件到镜像内

第三行 在tmp 文件夹创建一个目录 testdir

为了清楚的看见镜像的存储结构,通过 docker build 构建镜像

3b379f66-8d80-11eb-8b86-12bb97331649.png

因为我的 docker 使用的是 overlay2 文件驱动,所以进入到/var/lib/docker/overlay2 ,使用 tree 查看

可以清楚的看到,dockerfile 的每一行命令都会生成一个镜像层

3b571f9e-8d80-11eb-8b86-12bb97331649.png

Docker容器操作

我们通过一个镜像可以轻松的创建一个容器,一个镜像可以有多个容器,在运行容器的时候,实际上是在容器内部创建了这个文件系统的读写副本,如下图所示

3b7c27b2-8d80-11eb-8b86-12bb97331649.png

容器的生命周期是怎么样的?

容器的生命周期一共有五个状态分别为

created 初建状态

running 运行状态

stopped 停止状态

opaused 暂停状态

deleted 删除状态

通过docker cretate进入容器的初建状态,然后通过docker start进入运行状态,通过docker stop进入停止状态,运行状态的容器可以通过docker pause让其变为暂停状态,为了详细的查看这些过程,我们实操一下

创建并启动容器

3ba83fa0-8d80-11eb-8b86-12bb97331649.png

通过docker create创建的容器处于停止的状态,使用docker start busybox进入启动状态

3bd0dda2-8d80-11eb-8b86-12bb97331649.png

当使用docker run创建并启动容器的时候,docker后台的执行逻辑为

首先检查本地是否有busybox镜像,不存在则取dockerhub中拉取

使用busybox镜像启动一个容器

分配文件系统,并在镜像的只读层外创建一个读写层

从docker ip池分配个ip给容器

运行镜像

可以进入交互模式么

同时使用-it 参数可以让我们进入交互模式,容器内部和主机是完全隔离的。另外由于此时的 sh 为 1 号进程,所以如果通过 exit 退出 sh,那么容器也就退出,所以对于容器而言,杀死容器中的主进程,那么容器也就会被杀死

通过docker stop停止容器,其原理是给运行中的容器给 sigterm 信号,如果容器为 1 号进程接受并处理sigterm,则等待 1 号进程处理完毕后就退出,如果等待一段时间后还是没有处理,则会通过发送sigkill命令强制终止容器

如何进入容器?

想要进入容器,有三种方案,分别是 docker attach,docker exec,nsenter 等

使用 docker attach 方式进入容器

3bfcc94e-8d80-11eb-8b86-12bb97331649.png

通过 docker ps -a 查看当前的进程信息

3c28d412-8d80-11eb-8b86-12bb97331649.png

可是当我们在进行窗口进行docker attach的时候,这个命令就不好用了,所以使用docker exec的方式

使用 docker exec进入容器

3c4906ba-8d80-11eb-8b86-12bb97331649.png

奇怪的发现居然是两个sh 进程,主要是因为,当我们使用 docker exec方式进入容器的时候,会单独启动一个 sh 进程,此时的多个窗口都是独立且不受干扰,也是非常常用的方式

删除容器

现在基本上知道了如何创建,启动容器,那么怎么删除容器呢

使用docker rm的方式删除容器

3c69e7a4-8d80-11eb-8b86-12bb97331649.png

如果此时,容器正在运行,那么需要添加-f的方式停止正在运行的容器

如果想要导出容器怎么操作呢

这简单,不过在导出之前先进入容器创建一个文件

3c9310de-8d80-11eb-8b86-12bb97331649.png

然后导出为文件

3ccbb5ce-8d80-11eb-8b86-12bb97331649.png

此时会在当前目录生成一个 busybox.tar 文件,此时就可以将其拷贝到其他的机器上使用

那如何导入容器呢

通过 docker import的方式导入,然后使用docker run启动就完成了容器的迁移

3ce4a9bc-8d80-11eb-8b86-12bb97331649.png

此时容器名称为 busybox:test,然后我们使用 docker run 启动并进入容器

3d012aba-8d80-11eb-8b86-12bb97331649.png

此时发现之前在/tmp创建的目录也被迁移了过来

仓库

容器的基本操作应该都会了,那么我们应该如何去存储和分发这些镜像,这就需要介绍下仓库;

我们可以使用共有镜像仓库分发,也可以搭建私有的仓库

仓库是啥玩意

钱钱仓库放钱,这个仓库放镜像。Github 放代码,我们理解镜像的仓库可以联想 Github 仓库。

在学习的过程中,不太能区分注册服务器和仓库的关系。注册服务器其实是用来存放仓库的实际机器,而仓库我们可以将其理解为具体的项目或者目录。一个注册服务器可以存放多个仓库,每个仓库可以存放多个镜像

公有仓库

Docker hub 是当前全球最大的镜像市场,差不多超过 10w 个容器镜像,大部分操作系统镜像都来自于此。

3d2ad252-8d80-11eb-8b86-12bb97331649.png

如何使用公共镜像仓库和存储镜像

注册 Docker hub

3d5a05ae-8d80-11eb-8b86-12bb97331649.png

创建仓库

3d96b3f0-8d80-11eb-8b86-12bb97331649.png

实战镜像推送到仓库

此时假设我的账户是 xiaolantest,创建一个 busybox 的仓库,随后将镜像推送到仓库中。

第一步:拉取 busybox 镜像

3dd53f58-8d80-11eb-8b86-12bb97331649.png

第二步:推送镜像之前先登录镜像服务器(注意用户名密码哦),出现 login Succeeded表示登录成功

3df0faa4-8d80-11eb-8b86-12bb97331649.png

第三步:推送之前还要做一件事,重新对镜像命名,这样测能正确的推动到自己创建的仓库中

3e156556-8d80-11eb-8b86-12bb97331649.png

第四步:docker push 到仓库中

3e438de6-8d80-11eb-8b86-12bb97331649.png

私有仓库

Docker 官方提供了开源的镜像仓库 Distribution,镜像存放于 Docker hub 的 Registry中

启动本地镜像仓库

3e438de6-8d80-11eb-8b86-12bb97331649.png

使用 docker ps查看启动的容器

3e7434e6-8d80-11eb-8b86-12bb97331649.png

重命名镜像

此时 Docker 为busybox镜像创建了一个别名localhost:5000/busybox,localhost:5000为主机名和端口,Docker 将会把镜像推送到这个地址。

3e8ef6c8-8d80-11eb-8b86-12bb97331649.png

推送镜像到本地仓库

3eba3af4-8d80-11eb-8b86-12bb97331649.png

删除之前存在的镜像

此时,我们验证一下从本地镜像仓库拉取镜像。首先,我们删除本地的busybox和localhost:5000/busybox镜像。

3edf0d52-8d80-11eb-8b86-12bb97331649.png

查看当前本地镜像

3f0b1bfe-8d80-11eb-8b86-12bb97331649.png

可以看到此时本地已经没有busybox这个镜像了。下面,我们从本地镜像仓库拉取busybox镜像:

3f42b9ce-8d80-11eb-8b86-12bb97331649.png

随后再使用 docker image ls busybox 命令,这时可以看到我们已经成功从私有镜像仓库拉取 busybox 镜像到本地了

总结

本篇文章从 Docker 容器圈到基本使用,写的应该蛮清楚了。另外说明一下,由于直接使用代码很可能导致格式排版混乱,所以全部采用截图的方式,更加直观和清晰,当然如有不妥之处也望大家指正。

责任编辑:lq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 操作系统
    +关注

    关注

    37

    文章

    6808

    浏览量

    123292
  • 编程语言
    +关注

    关注

    10

    文章

    1942

    浏览量

    34714
  • Docker
    +关注

    关注

    0

    文章

    457

    浏览量

    11849
收藏 人收藏

    评论

    相关推荐

    docker-compose配置文件内容详解以及常用命令介绍

    一、Docker Compose 简介 Docker Compose是一种用于定义和运行多容器Docker应用程序的工具。通过一个  docker-compose.yml  文件,您可
    的头像 发表于 12-02 09:29 265次阅读
    <b class='flag-5'>docker</b>-compose配置文件内容详解以及常用命令介绍

    如何在树莓派上安装Docker容器

    Pi官网 下载最新版本的Raspberry Pi OS。 使用SD卡写入工具将镜像写入SD卡:可以使用 Etcher 等工具。 将SD卡插入树莓派并启动。 2. 更新系统 在安装Docker之前
    的头像 发表于 11-11 11:38 512次阅读

    Docker运行环境安装

    作者:京东科技 林中 Docker是一个开放的平台,用于开发、发布和运行应用程序。Docker分离了应用程序和运行应用的基础设施,从而实现了软件的快速交付。利用docker提供的一系列功能,包括构建
    的头像 发表于 10-29 11:28 205次阅读

    手动构建Docker镜像的方法

    不推荐使用docker commit命令,而应该使用更灵活、更强大的dockerfile来构建docker镜像。
    的头像 发表于 08-05 15:30 516次阅读
    手动构建<b class='flag-5'>Docker</b>镜像的方法

    ARM平台实现Docker容器技术

    本帖最后由 Tronlong创龙科技 于 2024-7-26 08:51 编辑 什么是Docker? (1)Docker的架构Docker是一个开源的应用容器引擎,让开发者可打包他们的应用以
    发表于 07-25 14:36

    ARM平台实现Docker容器技术

    本帖最后由 Tronlong创龙科技 于 2024-7-19 16:50 编辑 什么是Docker? (1)Docker的架构Docker是一个开源的应用容器引擎,让开发者可打包他们的应用以
    发表于 07-17 11:05

    Jtti:Docker会替代调虚机吗

    Docker是计算虚拟化的一种方式,和使用虚拟机进行虚拟化是类似的。由于近几年Docker技术的流行和发展。所以单独介绍一下Docker。首先先回答下面一个问题。 1.Docker会替
    的头像 发表于 07-12 14:38 315次阅读
    Jtti:<b class='flag-5'>Docker</b>会替代调虚机吗

    关于Docker 的清理命令集锦

    这篇文章主要介绍了Docker 清理命令集锦,需要的朋友可以参考下 复制代码代码如下: docker kill $(docker ps -a -q)  删除所有已经停止的容器 复制代码代码如下
    的头像 发表于 06-13 15:56 372次阅读

    一文扫尽Nas常用Docker软件

    NAS(Network Attached Storage,网络附加存储)设备上的Docker软件选择取决于您的具体需求和用途。以下是一些NAS上常用的Docker软件推荐
    的头像 发表于 05-23 18:33 1818次阅读

    精通Docker网络:Bridge驱动深度解析

    除了使用 docker0 网桥外,用户还可以使用自定义的网桥,然后通过 --bridge=BRIDGE 参数传递给 docker daemon。
    的头像 发表于 03-31 15:58 1438次阅读
    精通<b class='flag-5'>Docker</b>网络:Bridge驱动深度解析

    ARM平台实现Docker容器技术

    什么是Docker? (1)Docker的架构 Docker是一个开源的应用容器引擎,让开发者可打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows机器上
    的头像 发表于 03-07 13:48 801次阅读
    ARM平台实现<b class='flag-5'>Docker</b>容器技术

    迅为3588开发板Ubuntu安装Docker

    迅为3588开发板Ubuntu安装Docker
    的头像 发表于 01-29 16:07 737次阅读
    迅为3588开发板Ubuntu安装<b class='flag-5'>Docker</b>

    TLT507-Docker容器部署方法说明

    TLT507-Docker容器部署方法说明
    的头像 发表于 01-26 09:49 468次阅读
    TLT507-<b class='flag-5'>Docker</b>容器部署方法说明

    RK3568-Docker容器部署方法说明

    RK3568-Docker容器部署方法说明
    的头像 发表于 01-22 10:12 1395次阅读
    RK3568-<b class='flag-5'>Docker</b>容器部署方法说明

    请问一下docker是怎么实现cpu隔离的?

    Docker 使用 cgroups(控制组)来实现 CPU 隔离。
    的头像 发表于 01-15 10:06 520次阅读