开发者学堂课程【Docker 入门第二课时:Docker 入门】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/50/detail/1008
Docker入门
1.1 回顾操作系统如何管理进程
首先登录到一个操作系统内,可以通过PS等操作来看到各式各样的进程,这些进程包括系统自带的或属于自身应用的或属于其他应用。
这些进程的特点:
1.可以相互看见,相互通信;
2.使用同样的文件系统;
3.使用同样的系统资源。
三个特点会带来的问题:
1.相互看见,能相互通信:意味着这些进程具有高级权限的进程,可以攻击其他进程;
2.使用同样的文件系统:这些进程可以对已有的数据进行增删改查,意味着高级权限的进程可以把其他应用所需要的进程删掉,破坏掉其他进程的运行;进程跟进程之间所需要的依赖可能会存在冲突,会给运用成本带来很大的压力;
3.使用同样的数据资源:应用跟应用之间会存在资源的强占问题,应用消耗很大CPU和内存的时候它会破坏其他应用的运行会导致其他应用没法正常的提供服务。
在这样的问题之下该如何解决:
1.资源视图隔离-namespace 可以采用这个技术来帮助对进程进行隔离,也就是在资源的视图上进行隔离;
2.独立的文件系统-chroot 给这些进程提供一个独立的运行环境,把一个子目录变成一个根目录,在视图级别进行隔离,可以有一个独立的文件系统,这样这个进程对这个文件系统的增删改查,都不会影响其他进程的使用。
3.资源控制使用率-cgroup 为了减少对其他进程的影响,可以限制资源使用率。
1.2 容器的概念:
容器,是一个具有视图隔离、资源可限制、独立文件系统的进程集合。
视图隔离就是能看见其他进程,拥有独立的主机名等;资源使用的控制率,帮助这个进程限制他的资源使用,比如两个g的内存大小,CPU的使用个数等;容器其实是一个进程集合,只不过是把系统的其他资源隔离开,拥有独立的一个视图视角;容器是具有独立的一个文件系统。
1.3 容器的优势:
使用系统上的资源,独立的文件系统内不需要具备内核相关的代码或者是工具,只需要提供这个容器所需的二进制以及配置文件甚至是依赖即可。
1.4 什么是镜像
运行容器需要的所有集合,我们称之为容器镜像。
采用Dockerfile来构建一个镜像,Dockerfile描述镜像构建的步骤。每一个构建步骤会对现有的文件系统进行添加文件,删除文件甚至修改已有的文件,这样会带来一个文件系统的变化,我们把这些变化成之为Changeset。
图1-4-1表示的是一个golang 的镜像,每一个带有颜色的方框表示每一次构建步骤所带来的影响以及构建的步骤描述等,把这些构件的步骤所产生的变化,依次作用到一个空的文件夹上,就能得到一个完整的镜像,除了changeset这种描述之外还会发现,changeset是能相互复用的,图1-4-1蓝色部分表示alpine镜像,绿色部分表示golang的自身变化,golang镜像是基于alpine镜像进行构建的,镜像之间是能相互复用的。
图1-4-1
changeset所带来的分层以及复用的特点的优势:
1.提高分发效率;
2.数据共享;
3.减少磁盘压力。
1.5 如何构建镜像
图1-5-1所示是一个Dockerfile,是用来描述构建一个golang的application。FORM golang表示以下的构建步骤是基于golang镜像进行构建的。
图1-5-1
图1-5-2中WORKDIR表示把接下来的构建步骤都在相应的具体目录下进行.
图1-5-2
图1-5-3中 copy表示可以把数集上的文件拷贝到容器内,也就是拷贝到镜像内。
图1-5-3
图1-5-4中RUN表示在这个具体的文件系统内执行相应的动作,比如go get表示下载golang程序的依赖,把它出来的二进制移到可检索的地方,比如目录下面。运行完毕之后,就可以得到golang的一个application。
图1-5-4
图1-5-5中CMD表示使用这样的一个镜像的时候,默认的程序的名字。把这里的名字叫做“app”。
图1-5-5
1.6 如何运行容器
1.从镜像仓库中把相应的镜像下载下来,比如想要下载busybox这个镜像,就可以通过docker pull这个命令就可以从远端的镜像仓库中把镜像数据下载到本地;
2.下载完毕之后,可以通过docker images来查看当前的本地镜像列表,具有什么样的镜像,就会给出一个完整的列表来;
3.在这个列表中选中想要的镜像,也就是busybox,选中就可以通过docker run 的方式来运行这个镜像。
1.7 小结
容器,就是和系统的其他部分隔离开的进程集合;
镜像,就是容器所需要的所有文件集合,具备一次构建到处运行的特点。
2.1单进程模型
容器是一组具有隔离特性的进程集合,在docker run的时候,会选择一个镜像来提供独立的文件系统,以及指定相应的运行程序。所指定的这个运行程序称之为Init进程,使用进程的时候,会发现Init进程启动时容器也随之启动,当Init进程退出了之后,容器也随之退出了,就可以认为容器的生命周期和Init进程是一致的。
容器内不只有一个Init进程,Init进程本身可以产生其他的执行层,或者是通过docker exec产生出来的运维操作也属于Init进程管理的范围内。当Init进程退出的时候他所负责的所有子进程也随之退出。也是为了防止资源的泄漏。
可能会产生的问题?
一个应用里面的程序可能是一个有状态的,可能产生一些有非常重要的数据,当一个程序退出被删除之后的数据也就随着丢失了,这对于应用方而言是不能接受的,所以需要将容器所产生出来的重要数据,给持久化。
2.2数据持久化
容器能将数据持有化到指定的目录上把这个目录,称之为数据卷。数据卷的生命周期是独立于容器的生命周期的,也就是说容器的创建运行停止删除,都跟数据卷的生命周期没有任何关系。
数据卷通常情况下,有两种使用方法:
1.通过bind的方式,也就是把输入集上的目录,直接bind到容器内,图2-2-1中可以通过-v加参数的方式来进行。-v左边的参数表示是数组内的目录而右边的参数表示容器内的目录。busybox可以将当时容器运行的时间写都到tmp目录下面来可以对所有的数据进行统一管理。
2.把这个目录的管理交给容器的运行引擎,也就是demo,首先,可以通过docker volume 方式来创建一个数据卷,这个数据卷的目录由docker来管理。采用同样的方式,这个命令的左边部分变成volume的名字。然后运行结果跟第一种是一样的。
2.3小结
数据卷是独立于容器的运行时而存在的。它可以帮助我们。快速的进行数据的持久化。这个就是我们所介绍的容器运营时的生命周期。
moby是目前最流行的一个容器管理引擎。moby daemon会提供有关于容器、镜像、网络以及volume的管理依赖一个最重要的组件就是containerd,containerd是一个容器引擎,是管理引擎是独立于moby daemon。可以对像提供有关于容器镜像的相关管理。
容器可能是由不同的容器运行时所创建出来,现在具有很多种容器虚拟化技术的技术方案。在这些不同容器运行时的解决方案下,需要提供一个灵活的插件化管理,这个shim可以针对不同的容器运营时所开发的,可以从containerd中脱离出来,通过插件的形式进行管理,除了能够支持插件化之外,动态接管还具备最重要的一个特性,就是不会影响到现有的容器运行。当我们moby daemon意外退出的时候,容器就没人管理了,那么他也会随之消失退出,会影响应用的运行,所以说containerd的存在意义是非常重要的,它实现了一个动态接管的能力,这是整体的moby容器管理引擎的架构分析。
VM就是利用虚拟化技术来模拟硬件资源,比如CPU内存等等,在这样模拟的硬件的情况之下就可以在一个输入机上建立guest os,也就是常说的安装一个虚拟机,每一个guest os都有独立的内核。在guest os之下,每个应用,都是相互独立的,因为在一个guest os内,看不见其他guest os的应用,VM可以提供一个更好的隔离效果。当然,这样的隔离效果也要有一定的代价,需要把一部分资源交给虚拟化,这样就很难充分利用现有的计算资源,而且每个guest os都需要大量的磁盘空间,每个操作系统可能占用比较大的磁盘空间。这样的缺点就催生了容器技术。
容器是针对进程而言的,所以容器无需guest os,只需要一个独立的文件系统提供他所需要运行的所有文件集合即可。所有的隔离都是进程级别的,所以容器的启动时间快于VM,容器消耗的磁盘空间也小于VM,隔离效果比VM差很多,因为容器消耗的资源少,所以提供的隔离效果比VM差很多。
容器和VM之间各有优势、劣势,在这种情况下,容器也在向着强隔离的方向进行发展。