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给自己定制一个“每日新闻”

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

面向对象的三大特性与类图

1. 面向对象编程的三大特点 Object-oriented programming (OOP) is a paradigm centered around the concept of objects, which can contain data and code to manipulate that data. The three major characteristics of object-oriented programming are encapsulation, in…

天童美语:为了得体退出的那一天,你一定要好好爱孩子

父母最大的成就就是孩子可以独立,自己完成自己的人生。为了得体退出的那一天,你一定要好好爱你的小孩,因为每一天都在过去。当我们站在孩子成长的十字路口,面对那个终将到来的退出时刻,心中总会涌起一股难以言表的情感…

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

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

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

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

课时157:脚本发布_简单脚本_功能函数

2.1.3 功能函数 学习目标 这一节,我们从 基础知识、简单实践、小结 三个方面来学习 基础知识 简介 需求:三条命令其实是一个组合,实现的是一个功能简单实践 实践 查看脚本内容 #!/bin/bash # 功能:打包代码 # 版本: v0.3 #…

代码随想录第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. 在这篇文章中,我们将深入探讨监督学习的概念、机器学习的要求以及学习和提高预测准确…

Kotlin 协程:从基础概念到开发实践

前言 上一篇文章 深入理解Android多线程开发:场景应用与解决方案解析 针对Android开发中的多线程应用场景和相应的解决方案做了一个梳理。 总结出了Android开发中多线程编程的几个重要点: 资源复用和优化切线程任务编排并结合示例说明了Kotlin协程在处理上述问题时的优势。 …

如何删除:systemctl status ztncui

要删除 systemctl status ztncui,需要卸载与该服务相关的程序,并停止和禁用该服务。以下是详细的步骤: 停止服务: sudo systemctl stop ztncui 禁用服务: sudo systemctl disable ztncui 删除服务文件:…

归纳贪心好题

很有趣的一道归纳贪心题目 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…

图像分隔和深度成像技术为什么受市场欢迎-数字孪生技术和物联网智能汽车技术的大爆发?分析一下图像技术的前生后世

图像分隔和深度成像是计算机视觉和图像处理领域的两项重要技术&#xff0c;它们各自有不同的技术基础和要点。 图像分隔技术基础&#xff1a; 机器学习和模式识别&#xff1a; 图像分隔通常依赖于机器学习算法&#xff0c;如支持向量机&#xff08;SVM&#xff09;、随机森林…