一、docker
什么是docker,解决了什么问题?
Docker解决了运行环境不一致所带来的问题,Docker会将配置文件进行统一管理;解决耗内存问题,Docker会一开始就为每个程序指定内存分配;让快速扩展,弹性伸缩变得简单1.
docker和虚拟机之间的区别是什么?
Docker和虚拟机都是一种虚拟化技术,但是它们有一些区别,有以下几点:
- Docker是一种轻量级的虚拟化技术,它只虚拟出来容器所需要的资源,而不需要模拟整个硬件和操作系统。Docker容器是基于宿主机的操作系统内核创建的,它们之间共享内核,但是有自己的命名空间和文件系统。Docker容器的启动速度很快,只需要几秒甚至毫秒,而虚拟机需要数分钟。
- 虚拟机是一种完全的虚拟化技术,它通过模拟硬件,并在硬件上安装操作系统来实现。虚拟机有自己的虚拟硬件和操作系统,它们之间完全隔离,不受宿主机的影响。虚拟机可以运行不同类型和版本的操作系统,比如Windows和Linux,而Docker容器只能运行与宿主机相同类型和版本的操作系统。
- Docker和虚拟机在资源利用率和隔离性上有优劣之分。Docker由于没有额外的操作系统层,可以节省大量的磁盘空间、内存和CPU资源,提高了资源利用率。但是Docker的隔离性相对较弱,容器之间可能会受到宿主机内核的影响或者相互影响。虚拟机则相反,由于有额外的操作系统层,会占用更多的资源,降低了资源利用率。但是虚拟机的隔离性很强,虚拟机之间不会相互干扰或者受到宿主机的影响。
因此,Docker和虚拟机有各自的适用场景和需求。Docker更适合于隔离不同的应用,比如前端、后端和数据库等,提高开发、测试和部署的效率。虚拟机更适合于隔离整个运行环境,比如云服务提供商通常采用虚拟机技术隔离不同的用户。
二、容器
什么是容器
本质上,它是一个特殊的进程。通过名称空间(Namespace)、控制组(Control groups)、切根(chroot)技术把资源、文件、设备、状态和配置划分到一个独立的空间。通俗点的理解就是一个装应用软件的箱子,箱子里面有软件运行所需的依赖库和配置。开发人员可以把这个箱子搬到任何机器上,且不影响里面软件的运行。
容器解决了什么问题?怎么实现的
容器技术是一种虚拟化技术,它可以让应用程序和它们的运行环境被打包成一个容器镜像,这个镜像可以在不同的操作系统和硬件平台上运行,保证了应用程序的一致性和可移植性12。容器技术解决了以下问题:
- 环境不一致:传统的开发和部署方式,往往会因为不同的操作系统、依赖库、网络配置等导致应用程序在不同的环境中表现不同,甚至出现故障。容器技术通过封装应用程序和它们的运行环境,避免了这种问题,使得应用程序可以在任何支持容器的平台上运行。
- 资源浪费:传统的虚拟化技术,如虚拟机,需要为每个应用程序分配一定的计算、存储、网络资源,而这些资源往往不能被充分利用,造成资源浪费。容器技术通过共享操作系统内核和资源,实现了更高的资源利用率和更快的启动速度。
- 管理复杂:传统的开发和部署方式,需要人工进行各种配置、安装、更新、监控等操作,而这些操作往往是重复的、繁琐的、易出错的。容器技术通过提供标准化的接口和工具,实现了应用程序的自动化部署、扩缩容、迁移、监控等功能,降低了管理复杂度。
容器技术也有一些缺点,比如:
- 安全风险:容器技术由于共享操作系统内核,可能存在一些安全隐患,比如容器之间的隔离不够完善,或者操作系统内核本身存在漏洞2。容器技术需要采取一些措施来保证容器的安全性,比如使用安全的镜像源、限制容器的权限、监控容器的行为等。
- 兼容问题:容器技术虽然可以在不同的平台上运行,但是也有一些限制和要求,比如需要支持容器的操作系统和内核版本、需要适配不同的网络和存储环境等。容器技术需要遵循一些标准和规范来保证容器的兼容性,比如使用开源的容器格式和引擎、使用通用的网络和存储接口等。
docker和容器之间的关系是什么
容器如何实现网络和存储?
容器可以通过以下几种方式实现网络和存储:
容器可以使用宿主机的网络命名空间,直接共享宿主机的网络接口和 IP 地址,这种方式称为 host 模式1。
容器可以使用独立的网络命名空间,拥有自己的网络接口和 IP 地址,这种方式称为 bridge 模式1。容器之间可以通过宿主机上的虚拟网桥(如 docker0)进行通信,容器与外界可以通过端口映射或者 iptables 规则进行通信1。
容器可以使用其他容器的网络命名空间,共享其他容器的网络接口和 IP 地址,这种方式称为其他容器模式1。容器之间可以通过 localhost 进行通信,容器与外界的通信方式与共享的容器相同1。
容器可以使用用户自定义的网络模式,使用第三方的网络驱动或者创建单独的 bridge 网络来定制容器的网络1。这种方式可以实现容器之间和外界的更灵活的通信,甚至可以实现跨主机的容器通信1。
容器可以使用 Pod 的概念,将一组相关的容器组合在一起,共享一个 IP 地址和一组端口2。这种方式是 Kubernetes 的核心抽象,可以实现容器之间和外界的高效通信2。
对于存储方面,容器可以使用以下几种方式实现存储:
容器可以使用宿主机上的文件系统,将宿主机上的目录或文件挂载到容器内部,这种方式称为卷(Volume)3。卷可以提供持久化、共享和可移植的存储能力3。
容器可以使用持久卷(Persistent Volume)和持久卷声明(Persistent Volume Claim)来抽象存储资源,并与底层存储提供商进行交互3。这种方式可以提供动态、可扩展和跨集群的存储能力3。
容器可以使用投射卷(Projected Volume)来将多个源(如 Secret、ConfigMap 等)投射到同一个卷中,并保持数据更新3。这种方式可以提供配置、凭证和其他敏感信息的存储能力3。
容器可以使用临时卷(Ephemeral Volume)来创建短暂的、非持久化的、与 Pod 生命周期绑定的存储空间3。这种方式可以提供缓存、日志等临时数据的存储能力3。
三、镜像
10个关于docker 镜像的问题
什么是docker镜像?
docker镜像和容器有什么区别?
docker镜像是如何构建的?
docker镜像有哪些常用的命令?
docker镜像有哪些优点和缺点?
docker镜像可以从哪里获取?
docker镜像可以如何管理和共享?
docker镜像有哪些格式和标准?
docker镜像可以如何优化和减小体积?
docker镜像有哪些安全和隐私的问题和解决方案?
什么是docker镜像
简洁解释
docker镜像是一种轻量级的、可执行的、独立的软件包,它包含了运行一个应用所需的所有内容,包括代码、库、环境变量和配置文件。docker镜像是由一系列的层组成的,每一层都是对上一层的增量修改。docker镜像是只读的,不能被修改,只能通过创建新的层来改变。
详细解释
docker镜像是由一系列的层组成的,每一层都是对上一层的增量修改。每一层都有一个唯一的ID,可以通过加密哈希算法或者随机数生成。docker镜像的所有层都是只读的,不能被修改,只能通过创建新的层来改变。
docker容器是基于docker镜像运行的实例,它在镜像的最上面添加了一个可读写的容器层。容器层保存了容器运行时的所有数据变化,如新建文件,修改文件等。删除容器后,容器层也会被删除,而基础镜像则保持不变。
docker使用了栈式层管理和写时复制的技术来实现镜像和容器的存储。栈式层管理是指每一层都是从下往上,以栈的方式组合在一起,组成镜像或者容器的根文件系统。写时复制是指当需要修改某一层的数据时,不直接修改原始数据,而是将修改后的数据保存在一个新的层中。这样可以提高效率和安全性,也可以实现镜像层之间的共享。
举个例子
假设有一个Dockerfile,内容如下:
FROM ubuntu:18.04
COPY . /app
RUN make /app
CMD python /app/app.py
这个Dockerfile包含四个指令,每个指令都会创建一个新的镜像层。第一条指令FROM ubuntu:18.04会从ubuntu:18.04镜像创建一个层,这个镜像本身也是由多个层组成的,我们可以用docker history命令查看它的层信息:
$ docker history ubuntu:18.04
IMAGE CREATED CREATED BY SIZE COMMENT
d131e0fa2585 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 months ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 3 months ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 3 months ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:eef57983bd66e3a7f… 63.2MB
可以看到,ubuntu:18.04镜像由五个层组成,每个层都有一个IMAGE ID,一个CREATED TIME,一个CREATED BY,一个SIZE和一个COMMENT。其中IMAGE ID是每个层的唯一标识,CREATED BY是创建这个层的指令,SIZE是这个层的大小,COMMENT是这个层的描述。注意最后一个层的IMAGE ID是d131e0fa2585,这也是ubuntu:18.04镜像的ID。
接下来,第二条指令COPY . /app会从当前目录下复制一些文件到镜像中的/app目录,这会创建一个新的层。我们可以用docker build命令来构建这个Dockerfile,并用docker history命令来查看新的镜像层信息:
$ docker build -t my-app .
Sending build context to Docker daemon 2.048kB
step 1/4 : FROM ubuntu:18.04
---> d131e0fa2585
Step 2/4 : COPY . /app
---> Using cache
---> bd09118bcef6
Step 3/4 : RUN make /app
---> Running in a07b694759ba
make: Nothing to be done for '/app'.
Removing intermediate container a07b694759ba
---> dbf995fc07ff
Step 4/4 : CMD python /app/app.py
---> Running in b9a8f9f6a7f5
Removing intermediate container b9a8f9f6a7f5
---> e8b1c1a8b6d1
Successfully built e8b1c1a8b6d1
Successfully tagged my-app:latest
$ docker history my-app
IMAGE CREATED CREATED BY SIZE COMMENT
e8b1c1a8b6d1 2 minutes ago /bin/sh -c #(nop) CMD ["python" "/app/app.p… 0B
dbf995fc07ff 2 minutes ago /bin/sh -c make /app 0B
bd09118bcef6 2 minutes ago /bin/sh -c #(nop) COPY dir:35a7eb158c1504e9… 100B
d131e0fa2585 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 months ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 3 months ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 3 months
四、层
层是什么结构
docker层是一种文件系统结构,它允许将多个只读文件系统叠加在一起,形成一个单一的虚拟文件系统。每个层都是对上一层的增量修改,可以添加,删除或更改文件和目录。docker层的优点是它们可以实现高效的存储和传输,因为只有变化的部分需要被保存和发送。
docker层有两种类型:镜像层和容器层。镜像层是由Dockerfile中的指令创建的,它们是只读的,不能被修改。容器层是在镜像层之上创建的,它是可读写的,用于保存容器运行时的数据变化。
docker使用联合文件系统(UnionFS)来管理和组织这些层。联合文件系统是一种特殊的文件系统,它可以将多个不同的文件系统挂载到同一个挂载点上,使它们看起来像一个文件系统。docker支持多种类型的联合文件系统,如aufs,overlay,overlay2等。
为什么镜像层的ID有的是missing?
docker history命令用于显示一个镜像的构建历史,它会列出每个镜像层的ID,创建时间,创建指令,大小和注释。
在docker 1.10之前的版本中,镜像层的ID是根据镜像层中的数据产生的一个随机码。在docker 1.10及以后的版本中,镜像层的ID是根据镜像层中的数据,使用加密哈希算法生成的。
当你使用docker history命令查看一个镜像的历史时,如果你看到某个镜像层的ID是,这表示这个镜像层是由另一个镜像继承过来的,而不是由当前镜像的Dockerfile创建的。
举个例子,假设你有一个名为my-app:latest的镜像,它是基于ubuntu:18.04镜像构建的。当你使用docker history命令查看my-app:latest镜像的历史时,你会看到类似下面的输出:
$ docker history my-app:latest
IMAGE CREATED CREATED BY SIZE COMMENT
e8b1c1a8b6d1 2 minutes ago /bin/sh -c #(nop) CMD ["python" "/app/app.p… 0B
dbf995fc07ff 2 minutes ago /bin/sh -c make /app 0B
bd09118bcef6 2 minutes ago /bin/sh -c #(nop) COPY dir:35a7eb158c1504e9… 100B
d131e0fa2585 3 months ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 3 months ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 3 months ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 3 months ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 745B
<missing> 3 months ago /bin/sh -c #(nop) ADD file:eef57983bd66e3a7f… 63.2MB
可以看到,my-app:latest镜像由八个层组成,其中前三个层是由my-app:latest镜像的Dockerfile创建的,它们都有一个具体的ID。而后面五个层是由ubuntu:18.04镜像继承过来的,它们都显示为。这并不表示这些层不存在或者丢失了,只是表示它们不属于当前镜像。
如果你想查看这些层的具体ID,你可以使用docker image inspect命令来查看镜像的元数据,其中包括每个层的ID和大小。
如何查看层的内容
使用 docker history或其他命令
层本质上是个一个文件吗
不完全是。层本质上是一个文件系统的子集,它包含了一些文件和目录,但不是一个完整的文件系统。层是通过联合文件系统(UnionFS)的技术实现的,它可以将多个文件系统叠加在一起,形成一个单一的虚拟文件系统。
你可以把层想象成一张透明的纸,上面有一些图案或文字,它们代表了镜像或容器中的一些数据。当你需要查看某张纸上的内容时,你不需要拿走它,只需要透过它就行了。这样可以节省空间和时间,因为你不需要复制或移动纸上的内容。当你需要修改某张纸上的内容时,你也不需要直接修改它,而是在它上面放一张新的纸,并把修改后的内容写在新纸上。这样可以保护原始数据不被破坏,也可以实现纸之间的共享。
一个层的 元数据和管理信息是存放在 基础层吗
不是的。一个层的元数据和管理信息是存放在存储驱动(Storage Driver)的专门目录中,而不是基础层。存储驱动是负责管理和组织层的文件系统,它可以是AUFS、OverlayFS、Btrfs等。存储驱动的目录通常位于 /var/lib/docker 下,每种存储驱动有自己的子目录结构和命名规则。例如,AUFS的目录结构如下:
- /var/lib/docker/aufs/diff:存放每个层的内容,每个层都有一个以层ID命名的子目录。
- /var/lib/docker/aufs/layers:存放每个层的元数据,每个层都有一个以层ID命名的文件,文件内容是该层所有父层的ID。
- /var/lib/docker/aufs/mnt:存放每个容器的联合挂载点,每个容器都有一个以容器ID命名的子目录。
关于 docker,容器,镜像,层,用更加形象的语言解释一下
可以把docker想象成一个厨房,你可以在厨房里做各种各样的菜肴。docker提供了一些工具和材料,让你可以方便地做出你想要的菜肴。
镜像就像是菜谱,它告诉你需要什么材料和步骤来做出一道菜。镜像是由一系列的层组成的,每一层就像是菜谱中的一条指令,告诉你要做什么。比如,第一层可能是从超市买回一些食材,第二层可能是把食材洗净切好,第三层可能是把食材放到锅里炒,等等。每一层都是对上一层的增加或修改,最终形成一道完整的菜。
容器就像是你做好的菜肴,它是一个可以运行的镜像实例。你可以根据镜像中的指示来做出一道菜,也可以在做菜的过程中添加一些自己喜欢的调料或变化。容器在镜像的最上面添加了一个可读写的容器层,这个层保存了你做菜时的所有数据变化,比如添加了什么调料,炒了多久等等。当你吃完这道菜或者不想吃了时,你可以把容器扔掉,这样容器层也会被删除,而基础镜像则保持不变。
层就像是透明的盘子,你可以把多个盘子叠在一起,形成一个堆叠。每个盘子上都有一些食材或调料,它们代表了镜像或容器中的一些数据。当你需要使用某个盘子上的内容时,你不需要拿走它,只需要看到它就行了。这样可以节省空间和时间,因为你不需要复制或移动盘子上的内容。当你需要修改某个盘子上的内容时,你也不需要直接修改它,而是在它上面放一个新的盘子,并把修改后的内容放在新盘子上。这样可以保护原始数据不被破坏,也可以实现盘子之间的共享。
k8s是为了解决什么问题
Kubernetes(k8s)是一个基于容器技术的的分布式架构解决方案,是Google开源的容器集群管理系统,主要用于自动部署、扩展和管理容器化的应用程序。它可以对分布式系统进行完美的支撑,具备完善的集群控制能力,内建有智能的负载均衡器,拥有强大的故障发现和自我修复能力。同时还针对开发、部署测试、运维监控等提供了完善的管理工具。
Kubernetes解决了容器化应用程序在分布式系统中部署、扩展和管理等问题。它可以让在其上构建的系统独立运行在物理机、虚拟机群或者云上,所以,Service (服务)是Kubernetes进行分布式集群构建的核心。
1.自动装箱:基于容器对应用运行环境的资源配置要求自动部署应用容器
2.自我修复(自愈能力)
- 当容器失败时,会对容器进行重启
- 当所部署的Node节点有问题时,会对容器进行重新部署和重新调度
- 当容器未通过监控检查时,会关闭此容器
- 直到容器正常运行时,才会对外提供服务
3.水平扩展:通过简单的命令、用户UI界面或基于CPU等资源使用情况,对应用容器进行规模扩大或规模剪裁
4.服务发现:用户不需要使用额外的服务发现机制,就能够基于Kubernetes自身能力实现服务发现和负载均衡
5.滚动更新:可以根据应用的变化,对应用容器运行的应用,进行一次性或批量式更新
6.版本回退:可以根据应用部署情况,对应用容器运行的应用,进行历史版本即时回退
7.密钥和配置管理:在不需要重新构建镜像的情况下,可以部署和更新密钥和应用配置,类似热部署。
8.存储编排:自动实现存储系统挂载及应用,特别对有状态应用实现数据持久化非常重要存储系统可以来自于本地目录、网络存储(NFS、Gluster、Ceph、Cinder等)公共云存储服务等