社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  docker

Docker底层实现 讲解

马哥Linux运维 • 5 月前 • 72 次点击  

下文中我说的可能对,也可能不对,鉴于笔者水平有限,请君自辨。有问题欢迎大家讨论


docker常用命令


上图是Docker的架构


整个Docker由客户端、服务端和仓库构成

常用命令

docker images 

docker search imagename

docker pull imagename:tag

docker rmi id/name

docker ps

docker run -it -p port1:port2 image



docker exec -it containername

docker stop containername

docker start containername

docker cp file containername:dir docker cp containername:dir file

docker inspect containername

docker rm containername

docker volume ls

docker save -o image

docker load xx.tar.gz


docker与虚拟机


docker出现的原因主要是解决传统的开发和运维方面的问题

case one:开发环境和生产环境可能不一致的问题,就比如一个项目刚开发的时候使用的MySQL是5.5版本,之后经过几轮开发,MySQL版本升级到了5.7,这个时候测试的版本还是5.5,在没有虚拟化技术之前,测试只有两个办法 1.删了重装 2.多装一个 就很麻烦。但虚拟化技术出现之后,直接远程docker pull,几分钟之内就能构建出一个MySQL5.7的环境

case two:在不同的开发环境中构建和运行应用程序可能会遇到很多问题。Docker可以将应用程序和依赖项打包到一个可移植的容器中,从而使得开发环境的设置变得更加简单和重复

case three:从安全性和速度上来说也比传统运维更加简单,可以很轻松的起成百上千个容器,并且这些容器在操作系统级别和硬件级别都存在隔离

一句话概括:通过Docker我们可以将**程序运行的环境也纳入到控制中 **

docker和虚拟机有何区别

docker绝对不是轻量级的虚拟机 绝对不是


docker是一个client-server结构的应用,守护进程运行在主机上,然后通过socket连接从客户端访问docker守护进程

一个docker容器,是一个运行时的环境,可以简单理解成进程运行的集装箱

docker和kvm(linux的内核虚拟机)都是虚拟化技术,主要差别在于:


  1. docker比虚拟机更少的抽象层,docker更加轻便和低成本

  2. docker利用宿主机内核  kvm需要guest os(直接在Host OS上多建一个OS),docker以MB硬盘为单位,kvm以GB为单位

  3. 在启动速度上 docker是秒级别的,而KVM是分钟级别的,和KVM相比,docker应用的性能高,同时系统的开销小



KVM在宿主机器的基础上创建虚拟层、来宾操作系统、虚拟化仓库,然后安装应用

容器在宿主机操作系统上创建docker引擎,在引擎的基础上安装应用

所以虚拟机是分钟级别 容器是秒级别

最核心的一点是:Docker和传统的VM虚拟机作比较的话,并不需要硬件的支持,只是进行了内核级别的虚拟化,像VM虚拟机是和真正的物理机器一样,对各种硬件都进行了虚拟化

docker技术底座

Linux命名空间 namespace 、控制组cgroup和unionFS  union file system三大技术支撑了目前Docker的实现 也是Docker能够出现的最重要原因

namespace

在linux中,namespace是在内核级别实现资源隔离的手段,不同的namespace程序可以享有一份独立的系统资源


namespace是linux为我们提供的用于分离进程树、网络接口、挂载点、进程通信等资源的方法,在日常使用linux的时候,如果我们在服务器上启动了多个服务,这些服务其实是会相互影响的,因为他们能互相可见,也可以访问宿主机上的任意文件,但我们更希望一台机器上的不同服务能做到完全隔离,就像运行在不同的机器上一样。Docker通过使用namespace来实现容器的隔离,每个容器都有自己的namespace,可以访问其内部资源而不会影响宿主机或者其他容器,这使得Docker可以轻松地创建、启动和停止容器

在这种环境下,一旦服务器的某一个服务被入侵,那么入侵者就能够访问当前机器上的所有服务和文件

通过这七个选项 我们能设置新的进程在哪些资源上和宿主机进行隔离

fork:当调用fork函数时,系统会创建新的进程为其分配资源,例如存储数据和代码的空间,然后把原来的进程值都赋值到新的进程中,只有少量值与原来不同,相当于克隆自己 fork的返回值 在父进程中:fork返回子进程的ID在子进程中:fork返回0

如果错误:fork返回一个负值


Linux的命名空间机制提供了以下其中不同的命名空间,包括

  • CLONE_NEW CGROUP

  • CLONE_NEW IPC 提供一个独立的进程间通信的机制,信号量、共享内存、消息队列等只在容器内部课见

  • CLONE_NEW NET 为容器提供一个独立的网络环境,使得容器内部的网络接口、IP地址、路由表和防火墙规则都只能在容器内部可见

  • CLONE_NEW NS

  • CLONE_NEW PID 容器的独立进程ID空间,容器内部的进程只能看到自己的进程ID,而不会影响宿主机或者其他容器的进程

  • CLONE_NEW USER 容器内的独立用户和用户组

  • CLONE_NEW UTS 容器内的独立主机名和域名

通过这些选项,我们可以在创建新的进程时设置哪些资源与宿主机器进行隔离

Linux最特殊的两个进程:pid为1的/sbin/init的进程,和pid为2的kthreadd进程,这两个进程都是被Linux的上帝进程idle创建出来的,前者负责执行内核的一部分初始化工作和系统配置,后者负责管理和调度其他的内核进程

当我们运行docker run或者docker start的时候,就会启动setNamespaces方法,设置进程、用户、网络和IPC相关的命名空间,然后作为Create的参数在创建新容器的时候完成设置

如果docker的容器通过Linux的命名空间完成了和宿主机进程的网络隔离,但是又没有办法通过宿主机的网络与整个互联网相连,就会产生很多限制,所以Docker中的服务还是需要与外界连接才能发挥作用,每一个用docker run启动的容器都具有单独的网络命名空间,Docker为我们提供了四种不同的网络模式

  • Host

  • Container

  • None

  • Bridge

Docker默认的网络设置模式:网桥模式,在这种模式下除了分配隔离的网络命名空间之外,Docker还会为所有的容器设置IP地址,当Docker服务器启动时,会创建新的虚拟网桥docker0,docker0会为每一个容器分配一个新的IP地址,并将docker0的IP地址设置为默认的网关,网桥docker0通过iptables中的配置与宿主机器上的网卡相连。每当有一个新的服务需要暴露给宿主机,就会给容器分配一个IP地址,同时向iptables追加一条新的规则。

Docker通过Linux的命名空间实现了网络的隔离,又通过iptables进行数据包转发,让Docker容器能够优雅的为宿主机或者其他容器提供服务

Cgroup

CGROUP解决的就是限制容器物理资源占用的问题

挂载点:Docker容器中的进程仍然能够访问或者修改宿主机上的其他目录,这是我们不希望看到的。

如果一个容器需要启动,那么它一定需要提供一个跟文件系统(rootfs),容器需要通过这个文件系统来创建一个新的进程,所有二进制的执行都必须要在这个跟文件的系统中。从而实现将容器需要的目录挂在到容器中,同时也禁止当前的容器进程访问宿主机器上的其他目录,保证了不同文件系统的隔离

我们通过NAMESPACE隔离了文件、网络和进程,但是不能提供物理资源上的隔离,比如CPU或者内存,如果一个容器正在执行CPU密集型的任务,那么就会影响其他容器的性能和效率,而CGROUPS就是能够隔离宿主机器上的物理资源,例如CPU 内存 磁盘IO等等

每一个CGROUP都是一组被相同标准和参数限制的进程,CGROUP之间有层级关系,可以从父类进程一些标准和参数

而Cgroup的核心是一个叫做cgroupfs的文件系统,位于linux内核中的/sys/fs/cgroup目录下。该文件系统允许用户在一个层次结构中创建、管理和监控cgroup,具体实现如下

  1. 创建cgroup层次结构,这个层次结构由一个或者多个cgroup组成,每个cgroup都代表一组进程,并拥有一组资源限制。

  2. 将进程添加到cgroup中,这个实现其实就是把进程加到task文件中

  3. 为cgroup分配限制资源,例如可以用cgroup/cpu/相关的文件来限制cpu的使用率

  4. 监控cgroup的资源使用

Union File System

Union File System是一种文件系统技术,可以将多个文件系统(通常是只读文件系统和可写文件系统)合并成一个虚拟文件系统,使其像一个文件系统,但实际上是由多个文件系统组成的。

在Docker中,UFS解决了镜像只读不可写的问题,同时也是Docker的基础文件系统

UFS的实现基于三种文件系统:

  1. 只读文件系统

是UFS的基础,通常包含操作系统的核心组件和基本文件系统。在Docker中,只读文件系统通常是一个Docker镜像提供的

  1. 可写文件系统

可写文件系统是一个额外的文件系统层,它覆盖在只读文件系统之上,用于保存容器中创建、修改和删除的文件。每个容器都有自己的可写文件系统层,使得容器之间的文件不会相互干扰,在Docker中,可写层是在容器运行时创建的

  1. 合并文件系统

将只读文件系统和可写文件系统合并而成的,使得容器可以访问只读文件系统和可写文件系统层中的文件,就像它们是一个单独的文件系统一样。

在DOCKER中还有另一个非常重要的问题-镜像

Docker镜像的本质其实就是一个压缩包 也就是一个文件

Docker镜像是如何构建:Docker中的每一个镜像都是由一系列只读的层组成的,DockerFile中的每一个命令都会在已有的只读层上创建一个新的层,类似于搭积木,镜像的每一层其实都只是对当前镜像进行了部分改动,当镜像被docker run命令创建时,就会在镜像的最上层添加一个可写的层,也就是容器层。


容器和镜像的区别就是 镜像只是可读的,而每一个容器其实等于镜像加上一个可读写的层,也就是同一个镜像可以对应多个容器

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/165301
 
72 次点击