[转帖]Docker相关的概念和原理
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相关的概念和原理的更多相关文章
- [转帖]Docker五种存储驱动原理及应用场景和性能测试对比
Docker五种存储驱动原理及应用场景和性能测试对比 来源:http://dockone.io/article/1513 作者: 陈爱珍 布道师@七牛云 Docker最开始采用AUFS作为文件系统 ...
- 【转帖】Hadoop — HDFS的概念、原理及基本操作
Hadoop — HDFS的概念.原理及基本操作 https://www.cnblogs.com/swordfall/p/8709025.html 分类: Hadoop undefined 1. HD ...
- Docker相关文档
网上找到的一个入门级Docker学习笔记,写的不错,值得一看. 转自:http://www.open-open.com/lib/view/open1423703640748.html#articleH ...
- Docker学习笔记,从原理到实践
什么是docker Docker是使用go语言基于LINUX内核的cgroup,namespace以及AUFS 类的 Union FS 等技术,对进程进行封装隔离的一种操作系统层面的虚拟化技术,由于隔 ...
- Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之ORACLE集群概念和原理(二)
ORACLE集群概念和原理(二) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...
- Java线程:概念与原理
Java线程:概念与原理 一.操作系统中线程和进程的概念 现在的操作系统是多任务操作系统.多线程是实现多任务的一种方式. 进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程 ...
- RabbitMQ基本概念和原理
RabbitMQ基本概念和原理 1.AMQP,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计. 2.Rabb ...
- LDAP服务器的概念和原理简单介绍
LDAP服务器的概念和原理简单介绍 1. 目录服务 目录是一个为查询.浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样.目录数据库和关系数据库不 ...
- Java注解的基本概念和原理及其简单实用
一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析 ...
- Docker —几个概念的理解
本文从一种使用场景来引出docker,并讨论了什么是镜像,容器,仓库,以及docker的相关概念. 试想一种使用场景: 我的wordpress 博客网站现在部署在阿里云服务器上,但是在后期的使用中我有 ...
随机推荐
- gitlab jenkins 安装笔记
gitlab gitlab ce是社区版本,ee是企业版本,称为gitee. https://packages.gitlab.com/gitlab/gitlab-ce/install 通过运行curl ...
- 神经网络入门篇:详解深层网络中的前向传播(Forward propagation in a Deep Network)
深层网络中的前向传播 先说对其中一个训练样本\(x\)如何应用前向传播,之后讨论向量化的版本. 第一层需要计算\({{z}^{[1]}}={{w}^{[1]}}x+{{b}^{[1]}}\),\({{ ...
- Python快速爬取车标网图片,以后不要说这什么车你不认识了!
知识不分边界...... 人,为什么要读书?举个例子: 当看到天边飞鸟,你会说:"落霞与孤鹜齐飞,秋水共长天一色."而不是:"卧靠,好多鸟."; 当你失恋时你低 ...
- 聊聊LiteOS事件模块的结构体、初始化及常用操作
摘要:本文通过分析LiteOS事件模块的源码,深入掌握事件的使用. 事件(Event)是一种任务间通信的机制,可用于任务间的同步.多任务环境下,任务之间往往需要同步操作,一个等待即是一个同步.事件可以 ...
- 大数据集群跨多版本升级、业务0中断,只因背后有TA
摘要:2021年4月21日,中国太平洋保险集团联合华为云完成了全球首例大数据集群跨多版本的大数据集群滚动升级. 本文分享自华为云社区<华为云FusionInsight助力太保跨多版本升级业务0中 ...
- JS的深浅复制,原来如此!
摘要:之所以会出现深浅拷贝的问题,实质上是由于JS对基本类型和引用类型的处理不同. 本文分享自华为云社区<js的深浅复制,一看就明白>,作者: 鑫2020. 浅复制的意思 浅复制是仅仅对数 ...
- 火山引擎ByteHouse:如何用OLAP引擎提升数字营销效果?
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 随着市场竞争的加剧,企业对数字营销投入的效果监测和优化需求日益增强,营销实时监控也成为企业提升运营效率的重要手 ...
- 国密证书 VS 传统 SSL 证书,到底区别在哪?
根据 Myssl.com 的统计,目前 99% 的互联网网站使用的是传统 RSA 算法的 SSL 证书.也许你会问,使用传统证书有什么影响吗?现阶段而言,确实没有什么影响.但我国绝大多数网站系统使用的 ...
- 【JAVA基础】MySQL配置
mySQL配置 数据库连接 初始化配置 --创建用户 并授权 create user 'injasup'@'%' identified by 'supplier@2023#!'; GRANT SELE ...
- Educational Codeforces Round 82 (Rated for Div. 2) A. Erasing Zeroes(超简单的写法)
题意: 统计间隔在1中0的个数 思路: 超简单写法,直接利用string的find.rfind函数即可 #include<bits/stdc++.h> using namespace st ...