容器核心知识简介,通过从容器是什么,为什么以及如何用三个方面简要说明容器的使用知识。
一,什么是容器?
"A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another. A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run an application: code, runtime, system tools, system libraries and settings."
参考官网的描述,容器是标准软件代码及期依赖打包的单位,方便从一个计算环境部署到另一个。docker容器镜像:是轻量级、能独立运行、可执行的打包系统,包含所有的运行依赖:代码,运行时,系统工具,系统库和配置。
从这段话描述似乎和我们印象中的虚拟机类似,笔者大学07年左右就有不少同学倒腾vm在物理机或虚拟机上安装操作系统,但是明显不同的点是在于一个词:“轻量级”,下面我们就来具体聊下容器是如何实现轻量级的。
容器与虚拟机的区别
看到上述两张对比图大家应该就比较清楚, 从直观简化版的理解是:虚拟机为了应用程序启动,首先就需要启动一个新的操作系统,这也是为什么会显得比较重,而对于容器,简而言之更多的是面向应用,通过应用层的隔离让不同应用共享同一个操作系统的资源,因而会看起来比较轻量级。笔者之前比较喜欢的一个例子就是:“虚拟机器可以理解为重启一台电脑,每次都需要分钟级,而容器可以理解为重启一次微信或者钉钉,应用小的话可以达到秒级”当然这只是非常简化版的举例,实际容器在应用隔离,资源,安全等层面做了非常多的工作。
容器
容器是应用层的抽象,将代码和依赖项打包在一起。多个容器可以在同一台机器上运行,并与其他容器共享操作系统内核,每个容器在用户空间中作为独立进程运行。容器比VM占用的空间更少(容器映像的大小通常为几十MB),可以处理更多的应用程序,并且需要更少的VM和操作系统。
虚拟机
虚拟机(VM)是将一台服务器转换为多台服务器的物理硬件的抽象。虚拟机监控程序允许多个VM在一台机器上运行。每个虚拟机都包含操作系统、应用程序、必要的二进制文件和库的完整副本,占用数十GB。VM启动速度也可能很慢。传统的虚拟化技术,例如:vmware、kvm、xen等目标是完整的虚拟机,为了运行应用除了部署应用及期依赖(一般几十mb),需要安装整个操作系统(几十个gb)。
二,为什么需要容器?
2.1 容器解决的问题
现代系统已经非常复杂,以前的应用部署大部分都是c/s或者b/s架构,部署一台应用服务器,加上数据库就能够应对大部分的应用场景,甚至通过一些桌面虚拟化的技术例如citrix等还能减少桌面端的部署让企业内部分布式体验更好。但是在互联网应用的场景下,通过微服务的部署,快速迭代等场景下,原始技术架构不能支撑实际业务需要,因而需要更加细粒度的调度工具,与云原生“不可变基础设施”的准则与容器不谋而合。
“Trash Your Servers and Burn Your Code: Immutable Infrastructure and Disposable Components”, Chad Fowler, 2013
当前应用系统变得更加复杂,不少应用是基于微服务架构进行设计与开发,相较于早期的几台服务器基于三层架构部署(presentation / application / data),服务器只需要(webserver / application server / database server)几种类别。
今天基于微服务的架构,则需要更多的软件中间件进行支持:mq, cache, database,elasticsearch等,而且大概率这些应用会部署在不同的环境要求中:专有云,公共云等。笔者在以前的企业服务项目中就对环境的差异性非常有感触,常常一套在内部开发环境运行挺好的应用,在客户的环境中就很难调得通,记得有一些因为webserver部署的问题就因为客户加域后机器的情况,调试一个通宵,想想如果是基于微服务的应用,那估计都部署好可能会有按周到月的不等的延期。应用本身就包含多种服务,这些服务也有自己依赖的库和软件包;实际项目中也存在多套环境的情况,如何快速的让这些应用部署和运行?
上述各种环境的组合会产生大的部署矩阵,开发人员在写代码的时候需要考虑不同的运行环境,运维人员则需要针对不同环境进行配置,研发的效能很难提升。对于项目团队中的成员来说都是非常难以维护。如何解决这个问题?
我们把目光转移动日常生活中,是否有类似的场景以及如何解决。幸运的是在传统行业也遇到过类似的问题:
运输行业最开始是有船,但是因为载具的不同导致运输效率不高,每一次运输货主与运输方都会担心因为物资类型的不同产生潜在损失,而运输方关注如何更高效的运货,产生更多的赢利。比如:小汽车平放在船上可能放不了多少,上下的叠放又可能影响压坏货物,再来点水果或者海产品,如果需要冷藏呢?如果每次摆放都是按上述分析的过程,则运输行业的成本和赢利都非常难以保证。实际的问题可以列举出以下的矩阵:
上面的图看起来是不是和系统部署的问题类似?聪明的运输行业工程师发明了集装箱解决这个问题:
所有货物,不论是上述的汽车,水果或者冷藏海鲜都使用统一的集装箱大小,每次在运输时候都可以统一的摆放和运输,这个过程实际上是定义最小调度单位的过程。
1961年6月国际标准化组织集装箱技术委员会成立后,开始着手制定国际集装箱标准。第一个国际集装箱标准系列表在1964年第三次大会上提出,分两个系列、九种箱型;1967年第五次大会上,又增加了第三系列三种箱型;1969年10月第六次大会上,在第一系列中增加1AA箱型;1974年第八次大会上又增加1BB和1CC两种箱型,同时将第二系列降格为技术报告;在1976年第九次大会上,第三系列也降格为技术报告。1991年5月第十六次大会上,又增加了1AAA和1BBB两种箱型。国际标准集装箱共有13种规格,其宽度均一样(2438 mm)、长度有四种(12 192 mm、9 125 mm、6 058 mm、2 991 mm)、高度有四种(2 896 mm、2 591 1mm、2438 mm、<2438 mm). - 百度百科
集装箱被誉为运输业与世界贸易最重要的发明。至此全世界火车、船运、港口的吊装机器都可以基于统一的标准设计,为后来大规模的国际贸易提供可能。
将集装箱打包的思想应用到软件打包与发布上,则可以为代码提供一个基于统一标准化的运输交付系统,这种技术也就被称为:container,英文里有集装箱的意义。中文里考虑“容器”一词更好的抽象性,所以在计算机领域一直使用。可以看下docker的图标就是大鲸鱼背着集装箱运输的形象:
有了容器化技术后,基于容器的编制与打包技术则有了统一的标准,所以的应用系统及期依赖被打包成一个标准的集装箱,让软件系统的交付更加高效。
2.2 docker容器的特性
2.3 docker容器的优势
容器技术是devops技术的核心技术之一,极大的减少开发到发布部署的交付时间。对比以前的开发与运维交互界面为代码包,配置等,现在交互界面的为打包好的镜像与配置。很多时候结合devops工具,通过流水线,可以自动生成镜像,进行发布部署,极大的提升发版的效率。
对于开发人员的优势:Build Once、Run Anywhere
容器支持环境的隔离性和可重复性。开发人员只需为应用创建一次运行环境,打包成容器就可以在其它支持容器的环境中运行,编排调度平台让容器的运行与底层硬件解耦,开发团队更加专注代码本身。
对于运维人员的优势:Configure Once、Run Anything
配置好标准的runtime环境、服务器就可以运行任何容器。这使得运维人员的工作更加高效、一致性和可重复。容器消除开发、测试、生产环境的不一致性。实际上笔者参与的多个中大型容器化支撑的项目,仅需提供基础的容器运行平台、定义好规则、编制好流水线等前期配置工作、后续的发布大部分都是开发团队直接触发发版即可。
三,容器的如何工作的?
我们以docker为例简要说明容器如何工作
3.1 docker的架构
Docker使用客户端-服务器、c/s体系结构。Docker客户端与Docker服务端对话(Daemon),后者负责构建、运行和分发Docker容器。Docker客户端和守护程序可以在同一台主机上,也可以将Docker客户机连接到远程Docker服务端。Docker客户端和后台程序通过UNIX套接字或网络接口使用REST API进行通信。另一个Docker客户端是Docker Compose,可以支持一套由多个容器组成的应用系统。
3.2 docker服务器
Docker服务端(dockerd)侦听Docker API请求并管理Docker对象,如图像、容器、网络和卷。服务端还可以与其他服务端通信以管理Docker服务。
mac上通过命令查看服务端应用:launchctl list | grep docker
重启服务:
launchctl stop application.com.docker.docker.19.24&& launchctl start application.com.docker.docker.19.24
或者启动应用:
open /Applications/Docker.app
3.3 docker客户端
Docker客户端(Docker)是Docker用户与Docker交互的主要方式。当您使用docker-run等命令时,客户机会将这些命令发送给dockerd,dockerd会执行这些命令。docker命令使用docker API。Docker客户端可以与多个服务端程序通信。
3.4 镜像
镜像是一个只读模板,包含创建Docker容器的说明。通常一个镜像基于另外的基础镜像构建,加上特化的依赖和配置项。例如,用户可以基于linux/java映像构建映像,自己配置安装Apache web服务器和应用程序,以及运行应用程序所需的配置详细信息。
用户可以创建自己的镜像,当然也可以使用镜像仓库已有镜像。要构建自己的映像,可以使用相应的语法创建Dockerfile,主要来定义创建映像和运行映像所需的步骤。Dockerfile中的每条指令都会在镜像中创建一个层。更改Dockerfile并重新生成镜像时,只会重新生成已更改的层。与其他虚拟化技术相比,这是容器镜像更加轻量级、小型和快速的部分原因。
3.5 容器
容器是镜像的可运行实例。用户可以使用Docker API或CLI创建、启动、停止、移动或删除容器。将容器连接到一个或多个网络,将存储连接到容器,甚至可以基于其当前状态创建新镜像。
默认情况下,容器与其他容器及其主机相对隔离。可以控制容器的网络、存储或其他底层子系统与其他容器或主机的隔离程度。
容器由其镜像以及创建或启动时提供给它的任何配置选项来定义状态。删除容器时,未存储在持久性存储中的任何状态更改都会默认删除。
3.6 镜像仓库
Docker镜像仓库主要用来存储Docker镜像。Docker Hub是一个公共使用的镜像仓库,默认情况下Docker配置为在Docker Hub上查找图像。用户也可以配置自己的国内镜像仓库或者私有化仓库。
使用docker pull或docker run命令时,会从镜像仓库里拉取镜像。使用docker push命令时,镜像被推送到配置的镜像仓库中。
四,mac常用命令附录
4.1 docker images
REPOSITORY: 仓库中镜像名称
TAG: 镜像的标签信息,比如 x.x、latest 表示不同的版本信息;
IMAGE ID:镜像的 ID, 如果您看到两个 ID 完全相同,那么实际上,它们指向的是同一个镜像,只是标签名称不同罢了;
CREATED:镜像最后的更新时间;
SIZE: 镜像的大小,优秀的镜像一般体积都比较小,这也是一般使用轻量级的 版本的原因;
4.2 docker pull
1、pull的镜像名称均为小写,可以在中央仓库中搜索到2、 指定版本号
4.3 docker ps 查看docker中运行的容器
4.4 docker run 启动容器
说明:
docker run先会去本地镜像仓库查找运行的镜像,找不到,则会去远程仓库拉取镜像,拉取完毕在运行镜像。
1) Docker 客户端执行docker run命令
2)Docker daemon发现本地没有httpd镜像
3)daemon从Dcoker Hub下载镜像
4)下载完成,镜像httpd被保存到本地
5)Docker daemon启动容器
参数说明
4.5 其它命令列表
docker run -i -t <image_name/continar_id> /bin/bash 启动容器并启动bash(交互方式)
docker run -d -it image_name 启动容器以后台方式运行(更通用的方式)
docker ps 列出当前所有正在运行的container
docker ps -a 列出所有的container
docker ps -l 列出最近一次启动的container
docker images 列出本地所有的镜像
docker rmi imagesID 删除指定的镜像id
docker rm CONTAINER ID 删除指定的CONTAINER id
docker diff 镜像名 查看容器的修改部分
docker kill CONTAINER ID 杀掉正在运行的容器
docker logs 容器ID/name 可以查看到容器主程序的输出
docker pull image_name 下载image
docker push image_name 发布docker镜像
docker version 查看docker版本
docker info 查看docker系统的信息
docker inspect 容器的id 可以查看更详细的关于某一个容器的信息
docker run -d image-name 后台运行镜像
docker search 镜像名 查找公共的可用镜像
docker stop 容器名/容器 ID 终止运行的容器
docker restart 容器名/容器 ID 重启容器
docker commit 提交,创建个新镜像
docker build [OPTIONS] PATH | URL | - 利用 Dockerfile 创建新镜像
4.6 进入容器
docker exec -it [容器id] /bin/bash
4.7 如何查看容器的挂载目录
docker inspect container_name | grep Mounts -A 20docker inspect container_id | grep Mounts -A 20
4.8 删除容器
1) 先停止所有容器
docker stop $(docker ps -aq)
2 )删除所容器
docker rm $(docker ps -aq)
4.9 删除镜像
1) 删除单个镜像
docker rmi <image id>
2) 删除所有镜像
docker rmi $(docker images -q)
五,参考文章
1)https://www.cnblogs.com/luoliyu/articles/11315114.html
2)《每天5分钟玩转docker技术》
3)https://blog.csdn.net/shandian534/article/details/120549105
4)docker官网:www.docker.com