docker容器基本原理简介

一、docker容器实例运行的在linux上是一个进程

1)、我们通过docker run 通过镜像运行启动的在linux上其实是一个进程,例如我们通过命令运行一个redis:

docker run -d --name myredis redis

在这里插入图片描述

2)、可以看到首先我们本地还没有redis镜像

Unable to find image 'redis:latest' locally

然后其就冲远程仓库拉取最新版本的redis镜像

latest: Pulling from library/redis

3)、然后我们可以看到镜像是一层一层的拉取的(镜像是分层的,一层一层从最基础的镜像往上叠)

c7a4e4382001: Pull complete 
4044b9ba67c9: Pull complete 
c8388a79482f: Pull complete 
413c8bb60be2: Pull complete 
1abfd3011519: Pull complete 

4)、拉取下来后,其就运行产生了一个镜像实例d3775e5e4a1659f2ee592a7e69482983d2aa70d35f814b9e4a64fd121c0f42cf

在这里插入图片描述

5)、可以看到linux宿主机已经有这个进程了

6)、然后我们通过docker exec -it d3775e5e4a1659f2ee592a7e69482983d2aa70d35f814b9e4a64fd121c0f42cf /bin/bash进入这个实例

在这里插入图片描述

可以看到我们进入了这个实例,然后其ps命令也没有,这个应该也是docker轻量化的体现,没必要的就不额外加

7)、我们进入到/usr/local/bin下面,就可以看到我们的redis相关的了。

在这里插入图片描述

8)、然后我们通过redis-cli连接下

在这里插入图片描述

二、Linux 联合文件系统

​ Linux 联合文件系统(Union File System,简称 UnionFS 或 UFS)是一种分层的文件系统,它用于将不同的文件系统的文件、目录集合在一起,形成一个单一的文件系统。直观简单来说,就是将不同文件目录整合到一个work工作目录,然后其使用了写时复制(copy-on-write),也就是当我们要对某个文件进行写操作的时候,将原来的再copy一份,在进行写操作的时候,不影响原来的文件,在这个新文件进行写。下面我们就用一个案例来说明

在这里插入图片描述

​ 我们可以看到,这里创建了4个目录:lowner、upper、merged、work:

​ 1、lowner目录我们是只读的,下面两个目录lowner、lowner2两个其下面创建两个文件。

​ 2、upper目录是可写的,我们在其下面创建了upper.txt文件。

​ 3、merged目录是我们联合合并lowner、upper目录形成的统一视图。有点类似于数据库的视图

​ 4、work目录被用于处理这些目录合并操作中的临时文件和元数据

​ 下面我们就通过具体的命令来将其合并:

mount -t overlay overlay -o lowerdir=./lowner/lowner1:./lowner/lowner2,upperdir=./upper,workdir=./work ./merged

在这里插入图片描述

可以看到我们通过overlay挂载形成联合文件系统后,其将只读的lownerupper目录下面的所有文件都整合到merged目录下面了。

在这里插入图片描述

​ 我们进入到merged目录下面

在这里插入图片描述

​ 我们在merged下面将lower1.txtupper.txt进行修改

在这里插入图片描述

​ 可以看到在upper下面,由于我们修改了lower1.txt文件,写时复制,所以在upper可写目录下面产生了新的文件

在这里插入图片描述

​ 新写的不影响原来lowner只读的文件,而upper是可写的,所以upper.txt直接在原来的上面改的。

​ 我们前面在运行redis容器实例拉取镜像的时候,其是一层一层拉取的,,也就是容器镜像也是这样一层、一层由基础的只读、还有可写的联合起来的,最底层的与linux相关的,则是与linux宿主机使用相同的文件,当容器运行时,它会在一个可写的上层(upper layer)中进行修改,而原始镜像层(lower layers)则保持不变,这也是镜像轻量化的一部分使用体现。

三、Namepsace

​ namespace是Linux提供的一种内核级别环境隔离的方法,主要是为了实现资源隔离。例如我们的不同的容器实例,是相互隔离的,它们都可以有pid为1的进程。还有网络隔离,挂载隔离这些。

1、不同Namespace介绍

1. PID Namespace

​ PID Namespace允许进程拥有其自己的PID空间

2. Mount Namespace

​ Mount Namespace允许进程拥有其自己的文件系统挂载点视图。这允许容器在其自己的文件系统树中挂载和卸载文件系统,而不会影响宿主机。

3. UTS Namespace

​ UTS Namespace允许进程拥有其自己的主机名和域名。

4. Network Namespace

​ Network Namespace允许进程拥有其自己的网络栈。这允许容器拥有其自己的网络接口、路由表、防火墙规则等。

5. IPC Namespace

​ IPC Namespace允许进程拥有其自己的IPC资源,如消息队列、信号量等。这有助于隔离进程间的通信。

6、User Namespace

​ User Namespace 主要是用来隔离用户和用户组的。

2、PID案例

我们的Java程序:

import java.util.Random;public class TestCPU {public static void main(String[] args) {System.out.println("start exec ");while (true){Random random = new Random();double c =  random.nextDouble() * random.nextDouble();}}}

​ 这个也就是一直循环计算一个数。

在这里插入图片描述

下面我们来看一个基本的PID案例:

root@k8s-master namespace]# echo $$
40682
[root@k8s-master namespace]# 
[root@k8s-master namespace]# ls -l /proc/1/ns/
总用量 0
lrwxrwxrwx 1 root root 0 615 22:41 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 615 22:41 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 615 22:41 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 615 22:20 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 615 22:41 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 615 22:41 uts -> uts:[4026531838]
[root@k8s-master namespace]# 
[root@k8s-master namespace]# ls -l /proc/40682/ns/
总用量 0
lrwxrwxrwx 1 root root 0 615 22:41 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 615 22:41 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 615 22:41 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 615 22:41 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 615 22:41 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 615 22:41 uts -> uts:[4026531838]
[root@k8s-master namespace]# 

​ 在这个案例中我们可以看到通过echo $$输出当前的shell环境线程号PID为40682,由于其本身是从最顶级的父线程1fork的,可以看到我们ls -l /proc/1/ns/ls -l /proc/40682/ns/两个输出的不同namespace的的编号是相同的,然后其的pid都是4026531836,下面我们通过unshare --pid --fork --mount-proc /bin/bash命令,这个命令就是从读取相处fork一个子线程,然后其的pid不共享,也就是独立。

[root@k8s-master home]# ls -l /proc/1/ns
总用量 0
lrwxrwxrwx 1 root root 0 6月  15 22:41 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 6月  15 22:41 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 6月  15 22:41 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 6月  15 22:20 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 6月  15 22:41 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 6月  15 22:41 uts -> uts:[4026531838]
[root@k8s-master home]# ls
common  docker  feverasa  package  test  TestCPU.class  TestCPU.java  testq.sh  usspa
[root@k8s-master home]# nohup java TestCPU &
[1] 23952
nohup: 忽略输入并把输出追加到"nohup.out"
[root@k8s-master home]# ps -ef | grep java
root      23952  14436 99 23:34 pts/0    00:00:18 java TestCPU
root      24088  14436  0 23:34 pts/0    00:00:00 grep --color=auto java
[root@k8s-master home]# ls -l /proc/23952/ns
总用量 0
lrwxrwxrwx 1 root root 0 6月  15 23:34 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 6月  15 23:34 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 6月  15 23:34 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 6月  15 23:34 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 6月  15 23:34 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 6月  15 23:34 uts -> uts:[4026531838]
[root@k8s-master home]# unshare --pid --fork --mount-proc /bin/bash
[root@k8s-master home]# nohup java TestCPU &
[1] 39
nohup: 忽略输入并把输出追加到"nohup.out"
[root@k8s-master home]# ls -l /proc/39/ns
总用量 0
lrwxrwxrwx 1 root root 0 6月  15 23:36 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 6月  15 23:36 mnt -> mnt:[4026532634]
lrwxrwxrwx 1 root root 0 6月  15 23:36 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 6月  15 23:36 pid -> pid:[4026532635]
lrwxrwxrwx 1 root root 0 6月  15 23:36 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 6月  15 23:36 uts -> uts:[4026531838]
[root@k8s-master home]# ps -ef | grep java
root         39      1 99 23:35 pts/0    00:09:31 java TestCPU
root         73      1  0 23:44 pts/0    00:00:00 grep --color=auto java
[root@k8s-master home]# 

​ 在上面的案例中,我们首先直接在当前shell进程中启动一个java应用23952,其的PID Namespace为pid:[4026531836],与PID1的Namespace是一样的。然后我们通过unshare --pid --fork --mount-proc /bin/bash fork一个新的,PID Namespace隔离其他,再启动一个引用,然后该应用的的pid为39,然后其的pid为4026532635,并且我们ps -ef | grep java可以看到,其只能看到自己的java应用,看不到其父类的java引用,已经隔离了。

在这里插入图片描述

​ 另一个要说明的是,我们右边的窗口是最外面的父类的shell进程,可以看到其能看到自己的java应用23952,也能看到其子的java应用26527,同时这里也表面,子的隔离的PID39是被映射在父类是26527

[root@k8s-master feverasa]# ps -ef | grep java
root      23952  14436 99 23:34 pts/0    00:01:32 java TestCPU
root      26527  25519 99 23:35 pts/0    00:00:20 java TestCPU
root      26989  12613  0 23:35 pts/1    00:00:00 grep --color=auto java
[root@k8s-master feverasa]# 
[root@k8s-master feverasa]# ls -l /proc/23952/ns
总用量 0
lrwxrwxrwx 1 root root 0 6月  15 23:34 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 6月  15 23:34 mnt -> mnt:[4026531840]
lrwxrwxrwx 1 root root 0 6月  15 23:34 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 6月  15 23:34 pid -> pid:[4026531836]
lrwxrwxrwx 1 root root 0 6月  15 23:34 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 6月  15 23:34 uts -> uts:[4026531838]
[root@k8s-master feverasa]# ls -l /proc/26527/ns
总用量 0
lrwxrwxrwx 1 root root 0 6月  15 23:37 ipc -> ipc:[4026531839]
lrwxrwxrwx 1 root root 0 6月  15 23:37 mnt -> mnt:[4026532634]
lrwxrwxrwx 1 root root 0 6月  15 23:37 net -> net:[4026531956]
lrwxrwxrwx 1 root root 0 6月  15 23:37 pid -> pid:[4026532635]
lrwxrwxrwx 1 root root 0 6月  15 23:37 user -> user:[4026531837]
lrwxrwxrwx 1 root root 0 6月  15 23:37 uts -> uts:[4026531838]
[root@k8s-master feverasa]# 

​ Docker容器就是通过Linux 的Namespace来实现不同容器实例的资源隔离的。

四、cgroups

1、基本介绍

cgroups(control groups),是Linux内核的一个功能,用来限制、控制与分离一个进程组的资源,如CPU、内存、磁盘、输入输出等),在2.6.24版本合并到内核中去的。自那以后,又添加了很多功能。

Cgroups提供了以下功能:

​ 1.限制进程组可以使用的资源数量(Resource limiting )。比如:memory子系统可以为进程组设定一个memory使用上限,一旦进程组使用的内存达到限额再申请内存,就会触发OOM(out of memory)。

​ 2.进程组的优先级控制(Prioritization )。比如:可以使用cpu子系统为某个进程组分配特定cpu share。

​ 3.记录进程组使用的资源数量(Accounting )。比如:可以使用cpuacct子系统记录某个进程组使用的cpu时间

​ 4.进程组隔离(Isolation)。比如:使用ns子系统可以使不同的进程组使用不同的namespace,以达到隔离的目的,不同的进程组有各自的进程、网络、文件系统挂载空间。

​ 5.进程组控制(Control)。比如:使用freezer子系统可以将进程组挂起和恢复。

简单来说,其可以精细的控制一个进程对CPU、内存这些资源的使用,例如我们在运行docker实例的时候,控制控制其使用的内存、cpu这些docker run -itd --name test6 --cpu-quota 50000 centos:7 /bin/bash。下面我们就用一个控制CPU使用的案例来说明这点。

2、使用案例

首先我们创建自己的Cgroups

mkdir /sys/fs/cgroup/cpu/my_cgroups_cpu

在这里插入图片描述

​ 我们可以看到/sys/fs/cgroup这个目录下,,就是各种cgroup控制类型的目录,我们创建了一个cpu控制my_cgroups_cpu,其就有对应的目录,这个目录下面就是各种控制类型。

在这里插入图片描述

cpu.cfs_quota_us:表示一个调度周期内可以使用的CPU时间,单位为微秒。要限制CPU使用率为50%,可以将cpu.cfs_quota_us设置为50000(即50毫秒)。因为cpu.cfs_period_us默认为100000,所以50000/100000 = 0.5,即50%的CPU使用率。

​ 我们当前要控制的是cpu.cfs_quota_us,其作用是限制CPU的使用率,我们当前限制其的使用率为50%。

​ 我们先设置当前my_cgroups_cpucpu.cfs_quota_us50000

cgset -r cpu.cfs_quota_us=50000 my_cgroups_cpu

在这里插入图片描述

​ 首先我们运行一个不控制的应用,可以看到其对CPU100%

在这里插入图片描述

​ 下面我们加上控制来运行,将当前执行的java应用添加到cpu的cgroups控制中

cgexec -g cpu:my_cgroups_cpu java TestCPU

在这里插入图片描述

​ 可以看到我们后面启动的java应用对cpu使用率为50%

​ 我们当前通过上面的这几个基础的案例,说明了linux的联合文件系统、Namespace、Cgroups控制组,docker就是对linux这些功能进行封装,来形成docker镜像、容器实例这些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/28253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【LeetCode最详尽解答】11-盛最多水的容器 Container-With-Most-Water

欢迎收藏Star我的Machine Learning Blog:https://github.com/purepisces/Wenqing-Machine_Learning_Blog。如果收藏star, 有问题可以随时与我交流, 谢谢大家! 链接: 11-盛最多水的容器 直觉 这个问题可以通过可视化图表来理解和解决。 通过图形化这个…

「动态规划」如何求乘积最大子数组?

152. 乘积最大子数组https://leetcode.cn/problems/maximum-product-subarray/description/ 给你一个整数数组nums,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的…

【数据结构】初识集合深入剖析顺序表(Arraylist)

【数据结构】初识集合&深入剖析顺序表(Arraylist) 集合体系结构集合的遍历迭代器增强for遍历lambda表达式 List接口中的增删查改List的5种遍历ArrayList详解ArrayList的创建ArrayList的增删查改ArrayList的遍历ArrayList的底层原理 🚀所属…

【全栈实战】大模型自学:从入门到实战打怪升级,20W字总结(一)

😊你好,我是小航,一个正在变秃、变强的文艺倾年。 🔔本栏讲解【全栈实战】大模型自学:从入门到实战打怪升级。 🔔专栏持续更新,适合人群:本科生、研究生、大模型爱好者,期…

JVM-GC-什么是垃圾

JVM-GC-什么是垃圾 前言 所谓垃圾其实是指,内存中没用的数据;没有任何引用指向这块内存,或者没有任何指针指向这块内存。没有的数据应该被清除,垃圾的处理其实是内存管理问题。 JVM虽然不直接遵循冯诺依曼计算机体系架构&#…

基于flask的网站如何使用https加密通信-问题记录

文章目录 项目场景:问题1问题描述原因分析解决步骤解决方案 问题2问题描述原因分析解决方案 参考文章 项目场景: 项目场景:基于flask的网站使用https加密通信一文中遇到的问题记录 问题1 问题描述 使用下面的命令生成自签名的SSL/TLS证书和…

Docker镜像技术剖析

目录 1、概述1.1 什么是镜像?1.2 联合文件系统UnionFS1.3 bootfs和rootfs1.4 镜像结构1.5 镜像的主要技术特点1.5.1 镜像分层技术1.5.2 写时复制(copy-on-write)策略1.5.3 内容寻址存储(content-addressable storage)机制1.5.4 联合挂载(union mount)技术 2.机制原理…

用PHP来调用API给自己定制一个“每日新闻”

头条新闻汇聚了互联网上的时事动态,提供最新新闻动态、网络热门话题和视频更新等,覆盖社会、政治、体育、经济、娱乐、科技等多个领域,并不断刷新内容。企业应用这一接口后,可以快速吸引更多的用户访问自己的平台。即使是非新闻类…

有趣的傅里叶变换与小波变换对比(Python)

不严谨的说,时域和频域分析就是在不同的空间看待问题的,不同空间所对应的原子(基函数)是不同的。你想一下时域空间的基函数是什么?频域空间的基函数是什么?一般的时-频联合域空间的基函数是什么?小波域空间的基函数是什…

摄影师在人工智能竞赛中与机器较量并获胜

摄影师在人工智能竞赛中与机器较量并获胜 自从生成式人工智能出现以来,由来已久的人机大战显然呈现出一边倒的态势。但是有一位摄影师,一心想证明用人眼拍摄的照片是有道理的,他向算法驱动的竞争对手发起了挑战,并取得了胜利。 迈…

代码随想录第29天|贪心算法part3

134.加油站 首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈 每个加油站的剩余量rest[i]为gas[i] - cost[i] 从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置 因为我们一直维护的是一个剩余量大…

HCIA11 网络安全之本地 AAA 配置实验

AAA 提供 Authentication(认证)、Authorization(授权)和 Accounting(计费)三种安全功能。 • 认证:验证用户是否可以获得网络访问权。 • 授权:授权用户可以使用哪些服务。 •…

机器学习中的监督学习介绍

In this post well go into the concept of supervised learning, the requirements for machines to learn, and the process of learning and enhancing prediction accuracy. 在这篇文章中,我们将深入探讨监督学习的概念、机器学习的要求以及学习和提高预测准确…

归纳贪心好题

很有趣的一道归纳贪心题目 class Solution { public:int minimumAddedCoins(vector<int>& coins, int target) {sort(coins.begin(),coins.end());int n coins.size();int s 0,i0;int res 0;while(s<target){if(i<n&&coins[i]<s1)scoins[i];els…

顶顶通呼叫中心中间件-限制最大通话时间(mod_cti基于FreeSWITCH)

顶顶通呼叫中心中间件-限制最大通话时间(mod_cti基于FreeSWITCH) 一、最大通话时间 1、配置拨号方案 1、点击拨号方案 ->2、在框中输入通话最大时长->3、点击添加->4、根据图中配置->5、勾选continue。修改拨号方案需要等待一分钟即可生效 action"sched…

9M高速USB转接芯片CH347转双串口转I2C转SPI转JTAG转SWD

1、概述 CH347 TSSOP20封装和丝印 CH347 是一款高速 USB 总线转接芯片&#xff0c;通过 USB 总线提供异步串口、I2C 同步串行接口、SPI 同步串行接口和 JTAG 接口等。 在异步串口方式下&#xff0c;CH347 提供了 2 个高速串口&#xff0c;支持 RS485 串口收发使能控制、硬件流控…

LeetCode | 387.字符串中的第一个唯一字符

这道题可以用字典解决&#xff0c;只需要2次遍历字符串&#xff0c;第一次遍历字符串&#xff0c;记录每个字符出现的次数&#xff0c;第二次返回第一个出现次数为1的字符的下标&#xff0c;若找不到则返回-1 class Solution(object):def firstUniqChar(self, s):""…

Python自动化办公(一) —— 根据PDF文件批量创建Word文档

Python自动化办公&#xff08;一&#xff09; —— 根据PDF文件批量创建Word文档 在日常办公中&#xff0c;我们经常需要根据现有的PDF文件批量创建Word文档。手动操作不仅费时费力&#xff0c;而且容易出错。幸运的是&#xff0c;使用Python可以轻松实现这个过程。本文将介绍如…

linux的repo工具的入门

repo 是一个工具&#xff0c;用于管理 Git 仓库的集合&#xff0c;尤其在 Android 开发中被广泛使用。它是 Google 为 Android 项目开发的&#xff0c;以简化对大量 Git 仓库的管理。 主要特点 多仓库管理&#xff1a;repo 允许同时管理多个 Git 仓库&#xff0c;可以轻松执行…

MyBatis 的多级缓存机制是怎么样运作的?

引言&#xff1a;上周三&#xff0c;小 X 去面试一家中厂&#xff0c;其中面试官问到 MyBatis 的多级缓存机制是怎么样运行的&#xff1f;这个问题可以好好准备一下&#xff0c;很多人可能只会用 MyBatisPlus&#xff0c;简单的多表联查 SQL 语句可能都写不出来&#xff0c;更别…