https://www.jianshu.com/p/9737cbe33304

chroot

chroot就是可以改变某进程的根目录,使这个程序不能访问目录之外的其他目录。
Docker是利用Linux的Namespace、Cgroups和联合文件系统三大机制来保证实现的,它的原理是使用Namespace做主机名、网络、pid等资源的隔离,
使用Cgroups对进程或者进程组做资源的限制,联合文件系统用于镜像构建和容器运行环境。

Docker的命名空间

Docker主要用到一下五种命名空间:

  • pid namespace:用于隔离进程id。
  • net namespace:隔离网络接口。
  • mnt namespace:文件系统挂在点隔离。
  • ipc namespace:信号量,消息队列和共享内存的隔离。
  • ust namespace:主机名和域名的隔离。

Cgroups是一种unix内核功能,可以限制和隔离进程的资源使用情况。在容器的实现中,Cgroups通常用来限制容器的CPU和内存等资源的使用。

Docker有两个至关重要的组件:runC和containerd。

  • runC是Docker官方按照OCI容器运行时标准得到的一个实现。runC是一个用来运行容器的轻量级工具,是真正用来运行容器的。
  • containerd是从Docker中剥离出来的,containerd通过containerd-shim启动并管理runC,可以说containerd真正管理了容器的生命周期。

可以通过sudo ps aux|grep dockerd,查找到dockerd的pid,然后使用sudo pstree -l -a -A pid查看 docker组件之间的调用关系。

docker启动时,containerd就随之启动,dockerd与containerd一直存在。containerd会创建container-shim充当垫片进程,然后启动容器的真正进程。

镜像相关操作

镜像操作:

  • 拉取镜像,docker pull从本地拉取镜像获取从远程拉取镜像到本地;
  • 重命名镜像,docker tag重命名镜像
  • 查看镜像,docker images /docker image ls 查看现有镜像。
  • 删除镜像,docker rmi 镜像编号;
  • 构建镜像,docker build基于Dockerfile构建镜像,docker commit基于运行的容器提交为镜像。

Dockerfile操作

Dockerfile常用指令:

Dockerfile指令 指令介绍
FROM Dockerfile除了注释行,第一行必须是FROM,FROM后面跟镜像名称,作为基础镜像
RUN 跟具体命令,类似于Linux命令行的执行命令
ADD 拷贝本地文件或者远程文件到镜像内
COPY 拷贝本地文件到镜像内
USER 指定容器启动的用户
ENDPOINT 容器的启动命令
CMD CMD为ENDPOINT提供默认参数,也可以单独使用CMD指定容器启动参数
ENV 指定容器运行时的环境变量,格式为key=value
ARG 定义外部变量,构建镜像时可以使用build-arg=的格式传递参数用于构建
EXPOSE 指定容器监听的端口,格式为[port]/tcp或者[port]/udp
WORKDIR 为Dockerfile中跟在其后的所有RUN、CMD、ENDPOINT、COPY和ADD命令设置工作目录,只在当前有效

Docker清除数据的命令:

  • docker image prune -af 仅仅清除没有被容器使用的镜像文件
  • docker system prune -f 清除多余的数据,包括包含的容器、多余的镜像、未使用的volume等等。

Dockerfile书写原则:

  • 单一指责:一个Dockerfile只完成一个功能
  • 提供备注信息:提供注释信息
  • 保持容器最小化:只保留必要的内容
  • 合理选择基础镜像
  • 使用.dockerignore文件
  • 尽量使用构建缓存
  • 正确设置时区
    • Ubuntu和Debian系统: RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
      && RUN echo "Asia/Shanghai" >> /etc/timezone
    • Centos系统:RUN ln -sd /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
  • 使用国内软件源增加构建镜像构建速度
  • 最小化镜像层数。

Dockerfile书写建议:

  • Run指令在构建时会生成一个新的镜像层并且执行RUN指令后面的内容。

    • RUN指令后面跟内容复杂时,建议使用反斜杠结尾且换行;
    • RUN后面的内容尽量按照字母顺序排列,提高可读性。
  • CMD和ENDPOINT
    • CMD/ENDPOINT指令方式:CMD/ENDPOINT ["command","param"](exec模式,Docker 官方推荐的方式);
      CMD/ENDPOINT command param ,称为shell模式。
    • exec模式,容器的1号进程就是CMD/ENDPOINT指定的命令,shell模式启动的进程在容器中实际上并不是1号进程。
    • ENDPOINT可以和CMD指令结合使用,也可以单独使用,CMD只能单独使用。
    • Dockerfile中如果使用了ENDPOINT指令,启动Docker容器时需要使用--entrypoint参数才能覆盖Dockerfile中的ENDPOINT指令,
      使用CMD设置的命令,可以被docker run后面的参数直接覆盖。
  • ADD和COPY
    • COPY指令只支持基本的文件和文件拷贝功能,ADD则支持更多文件来源类型,比如自动提取tar包,并且可以支持源文件为URL格式。

基于内核的弱隔离系统如何保证安全

Docker与虚拟机的区别:

  • 虚拟机是通过管理系统(hypervisor)模拟出CPU、内存、网络等硬件,这样做的好处是虚拟机有自己的内核和操作系统,
    并且硬件是通过虚拟机管理系统模拟出来的,用户程序无法直接使用到主机的操作系统和硬件资源,虚拟机也对隔离性和安全性有着更好的保证。
  • Docker容器则是通过Linux内核的Namespace技术实现了文件系统、进程、设备以及网络的隔离,然后通过cgroups对CPU、内存等资源进行限制,
    最终实现容器之间互相不受影响,由于容器的隔离性仅仅依靠内核来提供,因此容器的隔离型也远弱于虚拟机。
Docker容器的安全问题 解决方法
Docker作为一款容器引擎,
本身也会存在一些安全漏洞
使用最新的版本,有相应的命名空间
镜像安全 私有镜像仓库自己进行扫描
Namespace隔离不够,然后部分关键
内容没有被安全隔离
宿主机内核应该尽量安装最新补丁;
使用capabilities划分权限;使用SELinux、
AppArmor、GRSecurity等安全组件加强安全;
每个容器都要限制资源使用
所有容器共享主机内核 使用安全容器来代替runC

cadvisor相关

cadvisor可以监控物理机和容器的状态;可以展示监控历史数据。
cadvisor的监控是基于cgroupsde。cgroups的工作目录是/sys/fs/cgroup,/sys/fs/cgroup目录,容器启动之后,可以在
/sys/fs/cgroup/memory/docker目录下查看内存相关的数据。memory.limit_in_bytes(限制总量)、memory.usage_in_bytes(使用量)。
如果监控网络信息,在/proc/{pid}/net/dev下面读取。

为什么容器需要Namespace

Namespace产生时间

命名空间与版本的关系:

Namespace名称 作用 内核版本
Mount(mnt) 隔离挂载点 2.4.19
Process(pid) 隔离进程id 2.6.24
Network(net) 隔离网络设备,端口号 2.6.29
Interprocess Communication(ipc) 隔离System IPC和POSIX Message Queue 2.6.19
UTS Namespace(uts) 隔离主机名和域名 2.6.19
User Namespace(user) 隔离用户和用户组 3.8
Control group Namespace 隔离cgroups根目录 4.6
Time Namespace 隔离系统时间 5.6

各个Namespace的作用

Mount Namespace

Mount Namespace用来隔离不同的进程或进程组看到的挂载点。
使用unshare命令可以新建Mount Namespace,并且在新建的Mount Namespace内Mount是和外部完全隔离的。

[root@centos7 centos]# sudo unshare --mount --fork /bin/bash
[root@centos7 centos]# mkdir /tmp/tmpfs
[root@centos7 centos]# mount -t tmpfs -o size=20m tmpfs /tmp/tmpfs
[root@centos7 centos]# ls -l /proc/self/ns

PID Namespace

PID Namespace的作用是用来隔离进程。

[root@centos7 centos]# sudo unshare --pid --fork --mount-proc /bin/bash
[root@centos7 centos]# ps aux # 查看进程

UTS Namespace

UTS Namespace主要是用来隔离主机名的,允许每个UTS Namespace拥有一个独立的主机名。

[root@centos7 centos]# sudo unshare --uts --fork /bin/bash
[root@centos7 centos]# hostname -b docker
[root@centos7 centos]# hostname

IPC Namespace

IPC Namespace主要是用来隔离进程间通信。

[root@centos7 centos]# sudo unshare --ipc --fork /bin/bash
[centos@centos7 ~]$ ipcs -q
[root@centos7 centos]# ipcmk -Q

ipcs -q命令:用来查看系统间通信队列列表。
ipcmk -Q命令:用来创建系统间通信队列。

User Namespace

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

[centos@centos7 ~]$ unshare --user -r /bin/bash # 如果没有权限,执行echo 65535 > /proc/sys/user/max_user_namespaces,然后再次尝试创建 User Namespace。

Net Namespace

Net Namespace用来隔离网络设备、IP地址和端口等信息。

[root@centos7 centos]#  sudo unshare --net --fork /bin/bash

如何通过Cgroups机制实现资源限制

cgroups主要功能:

  • 资源限制:限制资源的使用量,设置上限。
  • 优先级控制:不同的组可以有不同的资源使用优先级。
  • 审计:计算控制组的资源使用情况。
  • 控制:控制进程的挂起或恢复。

Cgroups功能的实现依赖与三个核心概念:子系统、控制组、层级树。

  • 子系统:是一个内核的组件,一个子系统代表一类资源调度控制器。
  • 控制组:一组进程和一组带有参数的子系统的关联关系。
  • 层级树:一系列的控制组按照树状结构排列组成的。
sudo mount -t cgroup # 查看当前系统已经挂载的cgroups信息

CPU子系统

在cpu子系统下创建cgroup

[root@centos7 centos]# mkdir /sys/fs/cgroup/cpu/mydocker

创建进程,加入cgroup

[root@centos7 centos]# cd /sys/fs/cgroup/cpu/mydocker
[root@centos7 centos]# echo $$ > tasks

执行CPU耗时任务,验证cgroup是否可以限制cpu使用时间

[root@centos7 centos]# cd /sys/fs/cgroup/cpu/mydocker
[root@centos7 centos]# echo 50000 > cpu.cfs_quota_us

memory 子系统

在memory子系统下创建cgroup

[root@centos7 centos]# mkdir /sys/fs/cgroup/memory/mydocker

创建进程,加入cgroup

[root@centos7 centos]# cd /sys/fs/cgroup/cpu/mydocker
[root@centos7 centos]# echo $$ > tasks

删除cgroups

[root@centos7 centos]# rmdir /sys/fs/cgroup/memory/mydocker

Docker组件机器原理

docker相关的组件:docker、dockerd、docker-init和docker-proxy。
containerd相关的组件:containerd、container-shim和ctr。
容器运行时相关的组件:runC。

dockerd

dockerd是Docker服务端的后台常驻进程,用来接收客户端发送的请求,执行具体的处理任务,处理完成后将结果返回给客户端。
Docker客户端与dockerd的交互方式:

  • unix套接字与服务端通信:配置格式为,unix://socket_path,默认为/var/run/docker.sock,该文件只有root或者docker用户可以访问。
  • TCP与服务端通信:可以配置为tcp://host:port
  • 文件描述符的方式与服务端通信:配置格式为: fd:// 这种格式一般用于systemd管理的系统中。

docker-init

init进程是1号进程,在docker run启动容器时可以添加--init参数,此时docker会使用docker-init作为1号进程。

docker-proxy

docker-proxy主要是用来做端口映射的。docker-proxy组件就会把容器内先赢的端口映射到主机上来,底层是依赖iptables实现的。

[root@centos7 centos]# sudo iptables -L -nv -t nat # iptables nat表的规则。

docker是官方实现的标准客户端,dockerd是Docker服务端的入口,负责接收客户端发送的指令并返回相应结果,docker-init在业务主进程没有进程回收功能,
docker-proxy组件是实现Docker网络访问的主要组件。

containerd

containerd不仅负责容器生命周期的管理,同时负责一些其他的功能:

  • 镜像的管理
  • 接收dockerd的请求,通过适当的参数调用runC启动容器;
  • 管理存储相关资源;
  • 管理网络相关资源;

containerd包含一个后台常驻进程,默认的socket路径为/run/containerd/containerd.sock,dockerd通过unix套接字向containerd发送请求,
containerd接收到请求后负责执行相关的动作并把执行结果返回给dockerd。

container-shim

container-shim的主要作用是将containerd和真正的容器进程解耦,使用container-shim作为容器进程的父进程,
从而实现containerd不影响已经启动的容器进程。

ctr

ctr是containerd-ctr,它是containerd的客户端,主要用来开发和调试。

runC

[root@centos7 centos]# cd  /home/centos
[root@centos7 centos]# mkdir runc # 创建runc运行根目录
[root@centos7 centos]# mkdir rootfs &&& docker export $(docker create busybox) | tar -C rootfs -xvf - # 导入rootfs镜像文件
[root@centos7 centos]# runc spec
[root@centos7 centos]# cat config.json
[root@centos7 centos]# runc run busybox # 启动容器
[root@centos7 centos]# cd /home/centos/runc
[root@centos7 centos]# runc list
组件分类 组件名称 作用剖析
Docker相关组件 docker Docker客户端,负责发送Docker操作请求
Docker相关组件 dockerd Docker服务端入口,负责接收客户端请求并返回结果
Docker相关组件 docker-init 业务主进程没有回收能力时,docker-init可以作为容器的1号进程,负责管理容器的内子进程
Docker相关组件 docker-proxy 用于Docker的网络实现,通过设置iptables规则使得访问到主机的流量可以转发到容器中
containerd相关组件 containerd 负责管理容器的生命周期,接收dockerd的请求,执行启动或者销毁容器操作
containerd相关组件 containerd-shim 将containerd和真正的容器进行解解耦,使用containerd-shim作为容器进程的父进程,可以实现重启containerd不影响已经启动的容器进程
containerd相关组件 ctr containerd的客户端,可以直接向containerd发送容器操作请求,主要用来测试和开发
容器运行时组件 runc 通过Namespace、Cgroups等系统接口,实现容器的创建和销毁

Docker网络模型

libnetwork常见的网络模式 作用 业务场景
null空间模式 不提供任何容器网络 处理一些保密数据,需要一个隔离的网络环境执行一些纯计算任务
bridge桥接模式 使得容器与容器之间网络可以互通 容器需要实现网络通信或者提供网络服务
host主机模式 让容器内的程序可以使用到主机的网络 容器需要控制主机网络或者使用主机网络提供服务
container网络模式 将两个容器放到同一个网络空间中,可以直接通过localhost本地访问 两个容器之间需要通过localhost通信

[转帖]Docker相关的概念和原理的更多相关文章

  1. [转帖]Docker五种存储驱动原理及应用场景和性能测试对比

    Docker五种存储驱动原理及应用场景和性能测试对比 来源:http://dockone.io/article/1513 作者: 陈爱珍 布道师@七牛云   Docker最开始采用AUFS作为文件系统 ...

  2. 【转帖】Hadoop — HDFS的概念、原理及基本操作

    Hadoop — HDFS的概念.原理及基本操作 https://www.cnblogs.com/swordfall/p/8709025.html 分类: Hadoop undefined 1. HD ...

  3. Docker相关文档

    网上找到的一个入门级Docker学习笔记,写的不错,值得一看. 转自:http://www.open-open.com/lib/view/open1423703640748.html#articleH ...

  4. Docker学习笔记,从原理到实践

    什么是docker Docker是使用go语言基于LINUX内核的cgroup,namespace以及AUFS 类的 Union FS 等技术,对进程进行封装隔离的一种操作系统层面的虚拟化技术,由于隔 ...

  5. Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)

    ORACLE集群概念和原理(二) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...

  6. Java线程:概念与原理

    Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...

  7. RabbitMQ基本概念和原理

    RabbitMQ基本概念和原理 1.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计. 2.Rabb ...

  8. LDAP服务器的概念和原理简单介绍

    LDAP服务器的概念和原理简单介绍 1. 目录服务 目录是一个为查询.浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样.目录数据库和关系数据库不 ...

  9. Java注解的基本概念和原理及其简单实用

      一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析 ...

  10. Docker —几个概念的理解

    本文从一种使用场景来引出docker,并讨论了什么是镜像,容器,仓库,以及docker的相关概念. 试想一种使用场景: 我的wordpress 博客网站现在部署在阿里云服务器上,但是在后期的使用中我有 ...

随机推荐

  1. 详解Vue八大生命周期钩子函数

    摘要:Vue为生命周期中的每个状态都设置了钩子函数(监听函数) .每当Vue实例处于不同的生命周期时,对应的函数就会被触发调用. 本文分享自华为云社区<一文带你弄懂Vue八大生命周期钩子函数&g ...

  2. 云图说|华为云自研云数据库GaussDB NoSQL,兼容多款NoSQL接口的数据库服务

    摘要:云数据库GaussDB NoSQL是一款基于计算存储分离架构的分布式多模NoSQL数据库服务,兼容多款nosql接口,在灵活弹性.快速扩展方面做到了极致. 本文分享自华为云社区<云图说|华 ...

  3. Docker 安装 ELK,EFK代替

    ELK 版本因为 前面 Elasticsearch 用的 7.9.3 版本,所以 kibana-7.9.3.logstash-7.9.3 都用 7.9.3 版本 安装配置 Elasticsearch ...

  4. python argparse传入布尔参数不生效解决

    前言 在一个需要用到flag作为信号控制代码中一些代码片段是否运行的,比如"--flag True"或者"--flag False". 但是古怪的是无法传入Fa ...

  5. 机器学习周刊 第4期:动手实战人工智能、计算机科学热门论文、免费的基于ChatGPT API的安卓端语音助手、每日数学、检索增强 (RAG) 生成技术综述

    LLM开发者必读论文:检索增强(RAG)生成技术综述! 目录: 1.动手实战人工智能 Hands-on Al 2.huggingface的NLP.深度强化学习.语音课 3.Awesome Jupyte ...

  6. Codeforces Round #629 (Div. 3) & 19级暑假第六场训练赛

    A:Codeforces 1328A Divisibility Problem 整除+模 Input 5 10 4 13 9 100 13 123 456 92 46 Output 2 5 4 333 ...

  7. Codeforces Round #700 (Div. 2) A ~ D1个人题解

    Codeforces Round #700 (Div. 2) 比赛链接: Click Here 1480A. Yet Another String Game 因为Alice是要追求小,Bob追求大值, ...

  8. nvm:npm的包管理器

    NVM: npm的包管理器 其实许久前就像写这个模块了,只是之前使用后又搁置了,今天下项目时node版本不一致,才想起记录 nvm下载地址: Releases · coreybutler/nvm-wi ...

  9. Intellij IDEA安装与配置教程(Windows版)

    Intellij IDEA(简称IDEA)是Java语言的集成开发环境,在业界公认为是一款优秀的Java开发工具.分为Community社区版(免费)和Untimate终极版(付费). IDEA是一款 ...

  10. OAuth2.0回调函数用html页面转发给controller

    OAuth2.0授权中有个回调函数,就是请求授权服务后,它会将你需要的code(假设code就是你需要的数据)发送给你的回调函数(你对外开放的一个url地址用以接收参数) 注:这个回调函数有点讨厌为什 ...