一文搞定Docker底层

博客:cbb777.fun

全平台账号:安妮的心动录

github: https://github.com/anneheartrecord

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

docker常用命令

一文搞定Docker底层_第1张图片

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

常用命令

// 查看镜像
docker images 

//搜索镜像
docker search imagename 

//拉取镜像 不声明则默认拉取最新版本 
docker pull imagename:tag 

//删除镜像
docker rmi id/name 

//查看容器
docker ps 

//启动容器
docker run -it -p port1:port2 image 
// -i 运行容器 -t 创建后进入命令行
// -p 端口映射 前者是宿主机端口 后者是容器内部端口

//守护方式进入容器(必须正在运行的容器)
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应用的性能高,同时系统的开销小

一文搞定Docker底层_第2张图片

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

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

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镜像提供的
2.可写文件系统
可写文件系统是一个额外的文件系统层,它覆盖在只读文件系统之上,用于保存容器中创建、修改和删除的文件。每个容器都有自己的可写文件系统层,使得容器之间的文件不会相互干扰,在Docker中,可写层是在容器运行时创建的
3.合并文件系统
将只读文件系统和可写文件系统合并而成的,使得容器可以访问只读文件系统和可写文件系统层中的文件,就像它们是一个单独的文件系统一样。

在DOCKER中还有另一个非常重要的问题-镜像
Docker镜像的本质其实就是一个压缩包 也就是一个文件

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

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

本文由mdnice多平台发布

你可能感兴趣的:(后端)