Docker 核心知识回顾
Docker 核心知识回顾
最近公司为了提高项目治理能力、提升开发效率,将之前的CICD项目扩展成devops进行项目管理。开发人员需要对自己的负责的项目进行流水线的部署,包括写Dockerfile 对自己的服务制作服务镜像。之前看过的东西,一段时间不用现在突然用起来还有些生疏。此篇对之前的Docker知识进行回顾加深。
对于docker 基本使用命令不再提及,遇到命令忘记或者不知道含义的时候可以使用 help 来进行查看。
基本架构
Docker 采用的是经典的C/S架构,包括客户端 和 服务端两大 核心组件。
Containers-shim:是containerd的子进程,为runc容器提供支持,也是容器内进程的 根进程
Dockerfiel
这里主要说一下Dockerfile 的编写注意的事项:
EXPOSE:只是申明镜像内监听端口,并不会完成自动映射。
ENV:当一条EVN指令 中同时为多个环境变量赋值 并且 值也是从环境变量中读取,会为变量都赋值后才更新
ENV key1 = valu1
ENV key1= valu2
ENV key2 = ${key1}
此时key1=valu2,key2=valu1
Context: 因为Docker是 C/S 架构的,在编写完Dockerfile 使用build 命令创建镜像的时候会将Dockerfile 所在路径下的数据作为上下文,传输给 服务端来创建镜像。所以如果我们Dockerfile同级目录下有多个文件,最好使用.dockerignore 来进行忽略,防止过多的数据发送到 docker服务端。
ADD\COPY : 都支持 go 语言格式的正则表达式。还有要注意路径的问题。
因为dockerfile 可以多步骤创建,所以最好 进行单一职责的划分,制作的镜像省略掉中间的环境,这样可以精简最终镜像的大小。
命名空间(重要)
命名空间是(namespace)是linux 内核的一个强大 特性。
操作系统中,包括内核,文件系统、网络、进程号、用户号、进程间通信 等资源都是进程间 直接共享的。想要虚拟化,那么除对 内存、cpu、网络IO等进行限制分割外,还需要实现文件系统、网络、PID、UID、IPC 等相互隔离。前面的好做限制,关键是后面的 文件系统、网络之类的如何隔离,这就需要系统的支持,也就是命名空间的引入了。
进程命名空间(较为重要):
每个进程命名空间有一套自己的进程号管理方法,
我们从 前面 基本架构 可以看到,他们的进程是进行继承的。
子空间对于父亲空间是可见,父空间对子空间不可见
linux 通过进程命名空间管理进程号,对于同一进程,在不同命名空间中,看到的进程号不一样。
$ ps -ef|grep docker
root 3393 1 0 Jan18 ? 0:43:02 /usr/bin/dcokerd ..
root 3398 3393 0 Jan18 ? 0:34:32 docker-containerd ...
我们在创建一个新的容器,执行 sleep 命令,然后在看看容器的 进程号(注意查看 父进程号)
$ docker run --name test -d linux sleep 9999
$ ps -ef|grep docker
root 21535 3398 0 0:57 ? docker-containerd-shim....
然后我们在 宿主机 查看新建容器的进程,也是 docker-containerd-shim 进程
$ ps -ef|grep sleep 9999
root 21569 21535 0 06:57 ? sleep 9999
重点:我们在容器内 查看进程
$ docker exec -it 3a bash -c 'ps -ef'
UID PID PPID C STME TTY TIME CMD
root 1 0 0 06:57 ? 00:00:00 sleep 9999
可以使用 pstree 命令,查看到完整的进程树
IPC命名空间:
容器中 进程交互 还是使用linux 进程间的交互方法,包括信号量、消息队列。同一个IPC命名空间,进程可以彼此可见,不同的则无法访问。
网络命名空间(重点)
有了进程间的命名空间,不用命名空间的进程信号可以相互隔离,但是,网络端口还是公用的,所以可以使用网络命名空间。
docker 采用虚拟网络设备,将不用命名空间的网络设备连接到一起。(默认网桥)
docker 可以使用四种网络模式:
Host :和主机公用一个网络,容器没有虚拟的网卡,没有独立的ip,和主机的网络是一样的。(但是文件之类的还是隔离的)
Container模式:和其他已存在的容器共享一个 Network Namespace, 不是和主机共享。
None模式:放在自己容器的网络内部中,外部访问不到,内部也访问不到外部。容器内部只能使用loopback网络设备不会再有其他网络资源。只能使用127.0.0.1的本机网络
Bridge模式:容器独立的使用 network Namespace,并链接到docker0虚拟网卡,通过docker0网桥以及Iptables nat表配置与宿主机通信;bridge模式是Docker默认的网络设置
当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,
此主机上启动的Docker容器会连接到这个虚拟网桥上。
虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
接下来就要为容器分配IP了,
Docker会从RFC1918所定义的私有IP网段中,选择一个和宿主机不同的IP地址和子网分配给docker0,
连接到docker0的容器就从这个子网中选择一个未占用的IP使用。
如一般Docker会使用172.17.0.0/16这个网段,并将172.17.0.1/16分配给docker0网桥(在主机上使用ifconfig命令是可以看到docker0的,可以认为它是网桥的管理接口,在宿主机上作为一块虚拟网卡使用)。
这里容器的访问控制 主要通过linux的 iptables 防火墙软件来控制的,
容器间的访问,这里是需要两个方面的支持
网络拓扑是否已经联通(默认都链接到docker0上一般都是互通的)
本地系统的防火墙软件iptables 是否允许访问通过,这取决于防火墙的规则
访问所有端口
当启动docker ,默认会添加一条‘允许’转发策略到iptables的 forward 链上,通过配置 -- icc=true|false 参数控制(启动docker 手动指定 iptables规则,不会影响 宿主机的iptables规则)
访问指定端口
可以通过 --link=container_name:allas 指定。(两个容器之间通过添加一条 ACCEPT规则)
对于容器访问外部。
转发过程:我们可以从上图看到,容器将请求通过 veth pair 接口给到docker 网桥,然后网桥通过docker0 发送到宿主机物理网卡上(其实dock er0 对应的就是一个网卡的端口) 网桥就是和交换机类似的作用。
- 这里请求要到外部,需要宿主机进行辅助转发,在宿主机器内查看是否允许 转发
sudo sysctl net.ipv4.ip_forward
- forward =1 则是转发,0则是关闭转发。
转发IP 变化:外部访问内部肯定不止直接访问 容器的IP了,需要进行源地址映射 SNAT(Source NAT),修改为宿主机 IP地址 10.0.2.2
具体操作:内部容器请求到达到主机向外部发送请求前,主机的ipstable 伪装源地址,ipstable 的 nat 表添加规则,将其源地址改为 主机地址 10.0.2.2(这个规则适用所用从docker 网桥的请求ip)
#iptables -t nat -A POSTROUTING -s 127.17.0.1/16 -o eth1 -j SNAT --to-source 10.10.0.186
## 解释规则:就是给nat表中 POSTROUTING 链 添加一条规则:从 s 过来的网段 (127.17.0.1/16) 都进行 snat 动作,即转换ip 为10.10.0.186
上边是针对企业中常应用的,但在家庭当中,很少有固定地址,一般都是动态地址,也就是说,出去的跳板是变动的,这样刚才所设置的规则就不行了,不过现在可以通过一个叫做 MASQUERADE—- 地址伪装来解决,即 snat 换成 MASQUERADE。
- 这里请求要到外部,需要宿主机进行辅助转发,在宿主机器内查看是否允许 转发
外部访问内部容器。
我们通过 容器启动时映射端口命令 -p 来添加容器到本机的端口映射,这其实也是在本地的 ipstable 添加 nat 规则,将外部IP 进行目标地址DNAT,将目标地址修改为容器内部ip 地址。
这里nat表设计两条链:
- PREROUTING 链 负责包到 网络接口时,改写器目的地址,其中的规则流量都到 docker 链,
- Docker 链将所有不是从docker0 进来的包(非本机器的产生的包),同时目标 端口为 docker0 映射的物理端口号(或者容器映射的端口号),修改目标地址为 172.2.0.2,目标端口使用 容器映射端口。
该图片来源于网络【https://blog.csdn.net/beanewself/article/details/78317626】
报文流向:
流入本机:PREROUTING --> INPUT-->用户空间进程 流出本机:用户空间进程-->OUTPUT--> POSTROUTING 转发:PREROUTING --> FORWARD --> POSTROUTING
不过还是建议,自定义一个网桥,这样方便自己管理容器的网络 。(使用openvswitch)
DNS
docker 服务启动后会默认启用一个 内嵌的 dns 服务,来自动解析同一个网络中的容器主机名和地址,如果无法解析,则通过容器内的dns 相关配置进行解析。
Docker启动容器时,会从宿主机 复制/etc/resolv.conf 文件,并删除掉无法链接的Dns 服务器。
挂载命名空间
挂载命名空间允许 不同命名空间的进程看到的本地文件位于宿主机的不同路径下,每个命名空间的进程看到的目录是彼此隔离的。
这里有 联合文件系统的知识,网络上很多讲解,这里我自己的理解为:
Docker 容器内部使用 联合文件系统,我们宿主机上看到的还是一个文件目录,只不过在docker 容器中相互隔离了。
这里要注意一点,对于可写层要读取下面的对象,如果 较为深层的对象 数据太大,意味着较差的IO性能。所以对于IO敏感型,推荐将容器通过 volume 方式挂载。
UTS命名空间
UTS 命名空间 允许每个容器拥有独立的主机名和域名,从而可以虚拟出一个独立的主机名 和网络空间的环境
用户命名空间
每个容器可以有不同的用户 和 组ID,也就是说,可以在容器内使用特定的内部用户 执行程序,而非本地系统存在的用户
控制组
这个是linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计。
资源限制:可以将组设置一定对内存限制,内存子系统可以对对进程组 设定一个内存使用上线
优先级:通过优先级 让一些组 优先得到更多的cpu 资源
资源审计:用来统计系统实际上把多少资源用到合适的目的上。
隔离:为组隔离命名空间,使得另一个组不会看到进程、网络等
控制:执行挂起、恢复 和重启
用户可以 /sys/fs/cgroup/memory/docker/目录下看到Docker组应用的各种限制项,用户可以修改这些值,来进行限制docker 应用资源。
compose
作为Docker 三剑客之一,它最主要的功能是服务编排。
这里只是简单的介绍 和 说明一些常用的语法
我们通过Dockerfile 可以快速的编写一个应用的镜像,但是我们的服务往往是 多个服务协作进行的:
比如前后端分离:前端一个服务、后端一个服务、再有一个数据库。。。
所以如果一个一个的写dockerfile 那么部署的时候也要进行先后配置,这显然不是Devpos初衷,我们想要的是一键部署,所以这就用到compose了。
我们可以使用compose 将各个服务进行依赖编写,然后同时部署多个容器。(在compose中,这叫做服务栈)
- 任务:一个容器被称为一个任务,任务有个独一无二的ID
- 服务:某个相同镜像的容器副本(一个前端,对应多个后端,多个后端就是副本)
- 服务栈:多个服务组成,相互配合完成特定业务。
使用一个web 应用作为例子:
version: '3' ##使用的compose版本
services: ## 定义一个服务
mall-admin: ## 服务容器配置信息
image: mall/mall-admin:1.0-SNAPSHOT ##镜像,也可通过build 构建镜像,
container_name: mall-admin
ports: ##容器端口
- 8080:8080
volumes: ##任务挂载路径
- /mydata/app/mall-admin/logs:/var/logs
- /etc/localtime:/etc/localtime
environment: ##启动入口
- 'TZ="Asia/Shanghai"'
external_links: ## 链接,通过这个可以做任务之间的依赖,容器之间可以访问。
- mysql:db #可以用db这个域名访问mysql服务
- nacos-registry:nacos-registry #可以用nacos-registry这个域名访问nacos服务
mysql:
image: mysql:5.7
container_name: mysql
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
restart: always
environment:
MYSQL_ROOT_PASSWORD: root #设置root帐号密码
ports:
- 3306:3306
volumes:
- /mydata/mysql/data/db:/var/lib/mysql #数据文件挂载
- /mydata/mysql/data/conf:/etc/mysql/conf.d #配置文件挂载
- /mydata/mysql/log:/var/log/mysql #日志文件挂载
swarm
我们上面解决了服务栈,也就是服务之间的依赖问题,但是我们现在都是微服务,需要的是一个服务部署多个机器,如果有上百个服务,成千的机器群,那我们部署排查,那不得忙的不可开交了么。所以docker 推出了swarm 来解决这个问题,就是对服务集群部署的解决。
Swarm 集群是一组被统一管理起来的docker 主机,集群是swarm 所管理的 对象,这些主机通过docker引擎的swarm模式相互沟通,
说白了,swarm是定义一个服务 部署多少个节点(部署在多少个主机上),然后对每个节点的容器服务进行监控管理的。这才是docker 真正运用在企业生产的地方。
Kubernetes
和swarm 拥有相同 的能力,只不过它更优秀,是谷歌公司开源的项目。
用户可以将配置模版提交之后,kubernetes 会自动管理(包括部署、发布、伸缩、更新)应用容器来维护指定状态。实现了十分高的可靠性 ,用户无需关心细节。
他的核心概念:每个对象包括三大属性:元数据、规范、状态。通过这三个属性,用户可以定义让某个对象处于给定的状态。这些对象存储在 Etcd高可用键值存储对象上(就是key-value形式,这个是分布式的存储,采用简洁的Raft共识算法(这里可以看之前的文章)),他自己本身也用的Raft共识算法来保证 一致性。
这里很重要,但是越来越觉得开发和运维分不开了,这完全是要开发做了运维的工作啊。。。目前用不到,之前尝试搭建过环境,直接把我云主机给干崩了(3个4G内存的机器),等以后用的时候可以在深入的看用法。
参考源:
- 《Docker技术入门与实战第三版》:机械工业出版社
- 网络博客【https://blog.csdn.net/beanewself/article/details/78317626】
Docker 核心知识回顾的更多相关文章
- Docker 与 K8S学习笔记(二)—— 容器核心知识梳理
本篇主要对容器相关核心知识进行梳理,通过本篇的学习,我们可以对容器相关的概念有一个全面的了解,这样有利于后面的学习. 一.什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,使应用程序可以在 ...
- 小D课堂 - 新版本微服务springcloud+Docker教程_5-01分布式核心知识之熔断、降级
笔记: 第五章 互联网架构服务降级熔断 Hystrix 实战 1.分布式核心知识之熔断.降级讲解 简介:系统负载过高,突发流量或者网络等各种异常情况介绍,常用的解决方案 1.熔断: ...
- C#基础知识回顾-- 反射(1)
C#基础知识回顾-- 反射(1) 反射(reflection)是一种允许用户获得类型信息的C#特性.术语“反射”源自于它的工作方式: Type对象映射它所代表的底层对象.对Type对象进行查询可以 ...
- python---基础知识回顾(六)网络编程
python---基础知识回顾(十)进程和线程(进程) python---基础知识回顾(十)进程和线程(多线程) python---基础知识回顾(十)进程和线程(自定义线程池) 一:Socket (一 ...
- Cookie详解、ASP.NET核心知识(7)
无状态的http协议 1.回顾http协议 Http协议是请求响应式的,有请求才有响应,是无状态的,不会记得上次和网页“发生了什么”. 关于http协议的这种特点,黑兔在前面的这三篇博文中进行了详细的 ...
- Java并发编程核心知识体系精讲
第1章 开宗明义[不看错过一个亿]本章一连串设问:为什么学并发编程?学并发编程痛点?谁适合学习本课?本课程包含内容和亮点?首先4大个理由告诉你为什么要学,其实源于JD岗位要求就不得不服了.其次5个痛点 ...
- oracle data guard --理论知识回顾01
之前搭建了rac到单实例的dg环境,最近又在windows下搭建了dg,这一篇关于dg的一些理论知识回顾 官方文档 https://docs.oracle.com/cd/E11882_01/nav/p ...
- [C#] C# 知识回顾 - 你真的懂异常(Exception)吗?
你真的懂异常(Exception)吗? 目录 异常介绍 异常的特点 怎样使用异常 处理异常的 try-catch-finally 捕获异常的 Catch 块 释放资源的 Finally 块 一.异常介 ...
- [C#] C# 知识回顾 - 学会处理异常
学会处理异常 你可以使用 try 块来对你觉得可能会出现异常的代码进行分区. 其中,与之关联的 catch 块可用于处理任何异常情况. 一个包含代码的 finally 块,无论 try 块中是否在运行 ...
随机推荐
- laravel 访问器 和修改器的使用
对于访问器我是这样定义的,就是将数据库中的数据被访问时可以变成我们想要的数据类型(例如:数据库中的时间字段是int类型,要将她变成data(Y-m-d H:i:s),格式类型) 参看博客 https: ...
- tp6微信公众号开发者模式token认证
微信公众号开发完整教程(一) PHP7.0版本,TP5.0框架 技术标签: 微信公众号开发 因为工作的需要,这一两年对微信公众号和小程序,项目制作的比较多.所以我才打算写一篇全面的 ...
- 二进制部署1.23.4版本k8s集群-6-部署Node节点服务
本例中Master节点和Node节点部署在同一台主机上. 1 部署kubelet 1.1 集群规划 主机名 角色 IP CFZX55-21.host.com kubelet 10.211.55.21 ...
- sklearn.preprocessing.Imputer,用来填充缺失值或者特定值的,相当于fillna()+dataframe结构中的排序问题
imp=Imputer()
- 软件工程homework-004
软件工程软件工程homework-004 博客信息 沈阳航空航天大学计算机学院2020软件工程作业 作业要求 https://edu.cnblogs.com/campus/sau/Computer17 ...
- LGP7884题解
是的,这是一篇使用 min25 筛的题解... 本题解参考command_block大佬的博客,代码是对其在 LOJ 上的提交卡常后写出来的. ML 板子把数据开到 \(10^{13}\) 速度还和供 ...
- c++-投骰子
#include<iostream>#include<cstdlib>//产生随机数的函数using namespace std;enum GameStatus{WIN,LOS ...
- kali下对Docker的详细安装
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 前言 Docker是渗透测试中必学不可的一个容器工具,在其中,我们能够快速创建.运行.测试以及部署应用程序.如,我们对一些漏洞进行本地复现时,可以 ...
- windows服务器怎么将证书添加到受信任证书颁发机构
1.键盘输入win+r 快键键,出现运行,输入mmc. 2.打开控制台根节点,点击上方导航栏的文件-->添加删除管理单元.如下图. 3.在可用的管理单元中选择"证书",计算机 ...
- EXCEL数据处理-经纬度转换:度分秒转换为小数
背景:工作中遇见此问题,整理了一下,花点时间随便总结下,希望能帮助到大家! 业务描述:红框内110°10′15"这种格式的经度,我想转换为110.36534这种格式. 步骤: 1.现将110 ...