docker容器的原理分析

 更新时间:2021年04月19日 10:13:06   作者:DBA随笔  
这篇文章主要介绍了docker容器的相关资料,帮助大家更好的理解和学习使用docker容器,感兴趣的朋友可以了解下

01 容器的本质是什么?

      今天的重点问题是讲述清楚什么是容器。

     要理解容器的概念,首先我们需要知道什么是进程?当我们在Linux操作系统执行一个程序,这个程序可能是一个二进制文件,它被调用的时候,变成了计算机内存中的数据、寄存器中的值、堆栈中的指令、以及各种设备状态信息的一个集合。像这样的一个计算机执行环境的综合,我们称之为进程。

   容器,就是为这个进程提供一个"边界",理解成白话,就是把这个进程"包"起来,它本质上是通过约束和修改进程的一些动态表现实现的这个"包"的动作。

    不难看出来,容器是一种特殊的、有"边界"的进程。

    现在我们来看一个MySQL容器的进程特点。

1、先查看下我们机器上mysql容器的containerID值,如下:

[root@VM-16-13-centos service]# docker ps | grep mysql
4784586d01e0        mysql                                                        "docker-entrypoint..."   3 months ago        Up 3 months                             k8s_mysql.16d54d16_mysql-pd7jr_default_0032bce0-2b0f-11eb-98ad-5254002dbd85_d775f414

可以看到,containerID的值是4784586d01e0

2、首先我们通过docker exec命令(关于这条命令的介绍,下面会有讲述)进入一个容器里面,ps -ef命令查看进程:

[root@VM-16-13-centos service]# docker exec -it 4784586d01e0  bash
root@mysql-pd7jr:/# ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
mysql        1     0  0  2020 ?        03:20:20 mysqld
root       882     0  0 09:42 ?        00:00:00 bash
root       888   882  0 09:46 ?        00:00:00 ps -ef

可以发现,mysqld这个进程的进程号是1.

这里我要多嘴一下:

1、docker exec -it 4784586d01e0 bash

这条指令是告诉容器,我要进入这个容器里面,并运行一个bash的指令。

2、如果你的docker里面不支持ps命令,你需要使用下面的命令安装一下ps这个指令:

apt-get update & apt-get install procps

然后我们退出到容器外面,再次查看mysqld进程的进程号:

[root@VM-16-13-centos service]# ps -ef|grep mysql
root      5152  5059  0  2020 pts/5    00:00:00 mysql -uroot -px xxxx
root     13644 24879  0  2020 pts/4    00:00:00 mysql -uroot -px xxxx
polkitd  18853 18837  0  2020 ?        03:20:25 mysqld

发现进程号是18853。

可以得到一个结论,mysqld进程在容器里面和容器外面执行的结果不一样。

为什么会这样?

其本质是docker容器中的进程被隔离在了一个新的环境中,使得这些进程只能看到重新计算过的PID号。前面我们说过,docker本质上是通过约束和修改进程的一些动态,将一个物理机上的进程"包"起来,我们看到的这个现象,就是"包"的结果。

那么Linux是如何将物理机进程进行的约束和修改呢?这里引入新的概念:

对于 Docker 等大多数 Linux 容器来说,Linux 的Cgroups 技术是用来制造约束的主要手段,而
Namespace 技术则是用来修改进程视图的主要方法。

02 Cgroup技术和Namespace技术介绍

    Namespace技术主要是为容器提供资源隔离用的。Namespace这个功能实现的方法比较简单,通常情况下,我们创建Linux进程的时候,系统会执行一个clone的命令,类似:

int pid = clone(main_function, stack_size, SIGCHLD, NULL);

它返回的就是我们创建的进程的PID号。

而Namespace技术就是在Linux创建进程的时候,多了一个参数,这个新参数暂且称之为newid,这样,在容器内,我们看到的进程的PID号,就是这个newid了。这个Namespace我们称之为PID Namespace。

    除了这个Namespace,还有其他的,例如mount Namespace,Network Namespace等,分别是为了隔离挂载点和隔离网络的。

    当然,不是所有的资源都能够被namespace化,例如时间和操作系统内核,就是一个服务器上的所有容器共享的。

    容器一旦开始运行,我们需要控制它使用的机器资源,例如磁盘、内存、CPU等,否则它可能会耗尽物理机的资源,导致一些系统进程发生崩溃。Cgroup技术就是专门为Linux进程限制资源使用的。它的全程是Linux Control Group,它以文件和目录的形式存放在/sys/fs/cgroups目录下,如下:

[root@VM-16-13-centos service]# ls -l /sys/fs/cgroup/
total 0
drwxr-xr-x 4 root root  0 Nov 20 11:38 blkio
lrwxrwxrwx 1 root root 11 Nov 20 11:38 cpu -> cpu,cpuacct
lrwxrwxrwx 1 root root 11 Nov 20 11:38 cpuacct -> cpu,cpuacct
drwxr-xr-x 5 root root  0 Nov 20 11:38 cpu,cpuacct
drwxr-xr-x 3 root root  0 Nov 20 11:38 cpuset
drwxr-xr-x 4 root root  0 Nov 20 11:38 devices
drwxr-xr-x 3 root root  0 Nov 20 11:38 freezer
drwxr-xr-x 3 root root  0 Nov 20 11:38 hugetlb
drwxr-xr-x 5 root root  0 Nov 20 11:38 memory
lrwxrwxrwx 1 root root 16 Nov 20 11:38 net_cls -> net_cls,net_prio
drwxr-xr-x 3 root root  0 Nov 20 11:38 net_cls,net_prio
lrwxrwxrwx 1 root root 16 Nov 20 11:38 net_prio -> net_cls,net_prio
drwxr-xr-x 3 root root  0 Nov 20 11:38 perf_event
drwxr-xr-x 4 root root  0 Nov 20 11:38 pids
drwxr-xr-x 4 root root  0 Nov 20 11:38 systemd

    不同的文件目录里面,存储不同的资源种类被限制的值,其中,比较常用的:

blkio:为块设备设置i/o限制,一般用于磁盘等设备

cpuset:为进程分配单独的CPU核心和对应的内存节点

memory:为进程设定内存使用的限制。

    当我们通过命令启动容器之后,操作系统会把这个docker进程对应的PID填写到对应控制组的文件中,从而控制当前进程使用的CPU资源值。

03 容器、镜像和仓库之间的关系

Docker 包括三个基本概念:

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

这三部分组成了Docker的整个生命周期,如上图所示。

docker镜像包含了文件系统,类似于虚拟机的镜像,它是只读的模板。这个文件系统也通常被称之为rootfs,通常包含了bin、etc、sys、usr等一系列目录。

docker容器是由镜像实例化而来的,这和我们学习的面向对象的概念十分相似,我们可以把镜像想象成类,把容器想象成类经过实例化后的对象,这样就非常好理解镜像和容器的关系了。

docker仓库:类似与代码仓库,是Docker集中存放镜像文件的场所

这个关系可以更加清楚的表述为:

以上就是详解docker容器的概念的详细内容,更多关于docker容器的概念的资料请关注脚本之家其它相关文章!

相关文章

  • docker-compose如何自定义network

    docker-compose如何自定义network

    文章介绍了在DockerCompose中如何通过networks配置定义和使用桥接网络,包括如何在docker-compose.yml文件中指定使用bridge网络,服务间的通信方式以及如何为服务分配特定的IP地址
    2025-01-01
  • docker中nginx卸载、安装、配置及挂载详细教程

    docker中nginx卸载、安装、配置及挂载详细教程

    这篇文章主要给大家介绍了关于docker中nginx卸载、安装、配置及挂载的相关资料,文中通过实例代码介绍是非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-09-09
  • win10家庭版安装docker遇到的问题小结

    win10家庭版安装docker遇到的问题小结

    这篇文章主要介绍了win10家庭版安装docker遇到的问题小结,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-10-10
  • idea连接docker实现一键部署的方法

    idea连接docker实现一键部署的方法

    这篇文章主要介绍了idea连接docker实现一键部署的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-10-10
  • docker 复制容器的项目实践

    docker 复制容器的项目实践

    本文主要介绍了docker 复制容器的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • Jenkins Docker静态agent节点的构建过程

    Jenkins Docker静态agent节点的构建过程

    这篇文章主要介绍了Jenkins Docker静态agent节点的构建,静态节点就是通过java -jar这条命令去启动起来就可以了,本文通过图文实例相结合给大家介绍的非常详细,需要的朋友可以参考下
    2021-10-10
  • 使用Shell脚本批量启停Docker服务

    使用Shell脚本批量启停Docker服务

    最近日常测试中经常需要手动启动或停止docker,于是决定写一个Shell脚本来代替人工操作,下面小编把我实现过程分享到脚本之家平台,需要的朋友参考下
    2019-11-11
  • 轻量级对象存储服务minio安装及浏览器使用教程

    轻量级对象存储服务minio安装及浏览器使用教程

    本次介绍了minio的安装及浏览器中的简单使用,对轻量级对象存储服务minio安装及使用教程感兴趣的朋友一起看看吧
    2021-10-10
  • Docker中搭建配置Git环境的过程

    Docker中搭建配置Git环境的过程

    工作中遇到了需要在Docker环境中操作GitLab仓库的场景,需要事先在Docker中搭好Git环境,但是很多朋友不是很清楚Docker配置Git环境的过程,今天通过本文给大家详细介绍下,需要的朋友参考下吧
    2021-08-08
  • 搭建一个私有的Docker registry教程

    搭建一个私有的Docker registry教程

    这篇文章提供了一个非常务实的方法来处理搭建私有Docker registry时出现的各种错综复杂的情况。我们将会使用一个运行于DigitalOcean(之后简称为DO)的非常小巧的512MB VPS 实例
    2016-09-09

最新评论