关于后端:一文搞定Docker底层

44次阅读

共计 4476 个字符,预计需要花费 12 分钟才能阅读完成。

博客:cbb777.fun

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

github: https://github.com/anneheartrecord

下文中我说的可能对,也可能不对,鉴于笔者程度无限,请君自辨。有问题欢送大家找我探讨

docker 常用命令

首先整个 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 利用的性能高,同时零碎的开销小

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 多平台公布

正文完
 0