02月9日, 2023
背景知识
容器技术的起源
假设你们公司正在秘密研发下一个“今日头条”APP,我们姑且称为明日头条,程序员自己从头到尾搭建了一套环境开始写代码,写完代码后程序员要把代码交给测试同学测试,这时测试同学开始从头到尾搭建这套环境,测试过程中出现问题程序员也不用担心,大可以一脸无辜的撒娇,“明明在人家的环境上可以运行的”。
测试同学测完后终于可以上线了,这时运维同学又要重新从头到尾搭建这套环境,费了九牛二虎之力搭建好环境开始上线,糟糕,上线系统就崩溃了,这时心理素质好的程序员又可以施展演技了,“明明在人家的环境上可以运行的”。
从整个过程可以看到,不但我们重复搭建了三套环境还要迫使程序员转行演员浪费表演才华,典型的浪费时间和效率,聪明的程序员是永远不会满足现状的,因此又到了程序员改变世界的时候了,容器技术应运而生。
有的同学可能会说:“等等,先别改变世界,我们有虚拟机啊,VMware好用的飞起,先搭好一套虚拟机环境然后给测试和运维clone出来不就可以了吗?”
在没有容器技术之前,这确实是一个好办法,只不过这个办法还没有那么好。
先科普一下,现在云计算其底层的基石就是虚拟机技术,云计算厂商买回来一堆硬件搭建好数据中心后使用虚拟机技术就可以将硬件资源进行切分了,比如可以切分出100台虚拟机,这样就可以卖给很多用户了。
你可能会想这个办法为什么不好呢?
容器技术 vs 虚拟机
我们知道和一个单纯的应用程序相比,操作系统是一个很重而且很笨的程序,简称笨重,有多笨重呢?
我们知道操作系统运行起来是需要占用很多资源的,大家对此肯定深有体会,刚装好的系统还什么都没有部署,单纯的操作系统其磁盘占用至少几十G起步,内存要几个G起步。
假设我有一台机器,16G内存,需要部署三个应用,那么使用虚拟机技术可以这样划分:
在这台机器上开启三个虚拟机,每个虚拟机上部署一个应用,其中VM1占用2G内存,VM2占用1G内存,VM3占用了4G内存。
我们可以看到虚拟本身就占据了总共7G内存,因此我们没有办法划分出更过虚拟机从而部署更多的应用程序,可是我们部署的是应用程序,要用的也是应用程序而不是操作系统。
如果有一种技术可以让我们避免把内存浪费在“无用”的操作系统上岂不是太香?这是问题一,主要原因在于操作系统太重了。
还有另一个问题,那就是启动时间问题,我们知道操作系统重启是非常慢的,因为操作系统要从头到尾把该检测的都检测了该加载的都加载上,这个过程非常缓慢,动辄数分钟,因此操作系统还是太笨了。
那么有没有一种技术可以让我们获得虚拟机的好处又能克服这些缺点从而一举实现鱼和熊掌的兼得呢?
答案是肯定的,这就是容器技术。
什么是容器
容器一词的英文是container,其实container还有集装箱的意思,集装箱绝对是商业史上了不起的一项发明,大大降低了海洋贸易运输成本。让我们来看看集装箱的好处:
- 集装箱之间相互隔离
- 长期反复使用
- 快速装载和卸载
- 规格标准,在港口和船上都可以摆放
回到软件中的容器,其实容器和集装箱在概念上是很相似的。
现代软件开发的一大目的就是隔离,应用程序在运行时相互独立互不干扰,这种隔离实现起来是很不容易的,其中一种解决方案就是上面提到的虚拟机技术,通过将应用程序部署在不同的虚拟机中从而实现隔离。
但是虚拟机技术有上述提到的各种缺点,那么容器技术又怎么样呢?
与虚拟机通过操作系统实现隔离不同,容器技术只隔离应用程序的运行时环境但容器之间可以共享同一个操作系统,这里的运行时环境指的是程序运行依赖的各种库以及配置。
从图中我们可以看到容器更加的轻量级且占用的资源更少,与操作系统动辄几G的内存占用相比,容器技术只需数M空间,因此我们可以在同样规格的硬件上大量部署容器,这是虚拟机所不能比拟的,而且不同于操作系统数分钟的启动时间容器几乎瞬时启动,容器技术为打包服务栈提供了一种更加高效的方式,So cool。
那么我们该怎么使用容器呢?这就要讲到docker了。
注意,容器是一种通用技术,docker只是其中的一种实现。
docker基本概念
什么是docker?
docker是一个用Go语言实现的开源项目,可以让我们方便的创建和使用容器,docker将程序以及程序所有的依赖都打包到docker container,这样你的程序可以在任何环境都会有一致的表现,这里程序运行的依赖也就是容器就好比集装箱,容器所处的操作系统环境就好比货船或港口,程序的表现只和集装箱有关系(容器),和集装箱放在哪个货船或者哪个港口(操作系统)没有关系。
因此我们可以看到docker可以屏蔽环境差异,也就是说,只要你的程序打包到了docker中,那么无论运行在什么环境下程序的行为都是一致的,程序员再也无法施展表演才华了,不会再有“在我的环境上可以运行”,真正实现“build once, run everywhere”。
此外docker的另一个好处就是快速部署,这是当前互联网公司最常见的一个应用场景,一个原因在于容器启动速度非常快,另一个原因在于只要确保一个容器中的程序正确运行,那么你就能确信无论在生产环境部署多少都能正确运行。
docker本质是容器技术
几个基本概念、名词
最重要的两个概念:镜像(image)、容器(container)
实际上你可以简单的把image理解为可执行程序,container就是运行起来的进程。
那么写程序需要源代码,那么“写”image就需要dockerfile,dockerfile就是image的源代码,docker就是”编译器”。
tar文件:docker save将一个镜像直接保存到tar文件,可以分享给别人,通过docker load指令就可以重新加载成一个镜像,然后通过docker run就能运行起来了
dockerfile:通过一个很短的配置文件,通过写“如何构建的步骤”,来指定一个镜像是如何创建的,docker build可以将dockerfile构建成一个镜像
docker官方仓库:有点类似于github,通过pull和push可以直接拉取镜像或者更新镜像。有很多程序支使用docker一键安装:比如ubuntu、nginx、mysql、python、tomact等等
练习
Play with Docker(PWD)介绍
- Play with Docker(PWD)是由Marcos Liljedhal和Jonathan Leibiusky发起的一个项目,由Docker公司赞助
- Play with Docker是一个网址,免费提供了一个在线的Docker操作平台,你可以在里面对Docker进行操作和学习
- 国内访问Play with Docker可能会非常满,因此需要进行翻墙才可以快速访问
使用步骤
第一步:进入官网https://labs.play-with-docker.com/,然后点击”Login”进行登录
第二步:点击”Login”之后会跳出一个界面,让你输入用户名和密码,这个用户名密码就是你在”Docker Hub”中的注册过的账号和密码
登录进去之后,界面如下,可以看到网站免费给你提供了4个小时的使用时间,当你使用完4个小时之后,需要退出重新登录就可以再次使用了
第三步:点击左侧的”ADD NEW INSTANCE”来添加一个新的实例,之后就会自动创建一个虚拟机,并提供给你一个命令行,该虚拟机已经包含了Docker环境,你可以直接在里面操作Docker
下载一个镜像
最简单的方法就是通过pull指令下载
我们先尝试下载nginx镜像
docker pull nginx
安装成功
实际上这一句命令等于docker pull nginx:latest
,也就是拉取最新版本的nginx,后面加latest就是最新版本,也可以加版本号。如果不指定版本默认就是最新版本
我们可以通过docker images
查看我们本地有哪些镜像
然后我们通过docker run nginx
来将这个镜像运行成一个容器, 但这样直接运行的话,会占用前台。这时我们可以通过一个参数来使其后台运行:
-d :后台运行
-p :指定端口映射 主机(宿主)端口:容器端口
docker run -d -p 80:80 nginx
通过docker ps
可以看到正在运行的程序有哪些
这时nginx已经运行在80端口了,我们主要到上面出现了端口按钮
点击即可访问这个服务
这说明docker成功运行
docker可以把同一个镜像启动为多个容器,只要端口不冲突就行
我们可以使用docker exec -it <容器id> bash
来进入容器:
容器id不用全部输入,只要前几位能识别出来就行
此时输入框前面显示的东西发生变化:变成了用户名+容器id
输入exit
可以退出容器
docker commit
可以把修改后的容器生成一个新的镜像
docker commit <容器id> <新的镜像名称>
dockerfile
需要学语法,用到再学
docker build
docker save >文件名称带后缀
将一个镜像保存到一个tar文件里
docker load
将一个tar文件加载为镜像
docker rm -f <容器id>
删除容器
docker rmi <镜像名称>
删除镜像
docker push
可以把本地的镜像上传到docker云上,就像github一样,需要登录账号。
参考文献
https://zhuanlan.zhihu.com/p/187505981