docker总结
编译docker
git clone https://github.com/docker/docker.git
-> 制作镜像
# wget http://www.yiyun.pro/docker-dev.tar
# docker load -i docker-dev.tar
-> C/S框架, 各模块松耦合:
Docker Daemon -> Engine -> Job
在Job运行时, 使用graphdriver -> 下载Graph(镜像), networkdriver 配置网络环境, execdriver 执行用户指令; libcontainer是容器管理包, 以上方法都在其中实现;
-> 主要模块:
client, daemon, register, graph, driver, libcontainer, container
client: 对众多container管理, 通过flag命令行执行;
daemon: 接受请求后, 通过路由交给相应的Handler 处理; Http.Server -> Mux.Router -> Handler <-> engine 通过与container仓库交互, 执行Job(例如执行进程, 下载文档)
registry:存储容器镜像; search, pull, push
graph: 不仅存储镜像, 存储镜像之间的元数据, ImageID...
driver: graphdriver, networkdriver, execdriver
libcontainer: 直接访问内核中与容器相关的API, namespace、cgroups、apparmor、网络设备以及防火墙规则;
container:体现在最终的交付, 包含: rootfs文件系统, 指定的计算资源, 隔离的网络环境, 自己的Job(App);
-> pull 与 run
docker pull命令的作用为:从Docker Registry中下载指定的容器镜像,并存储在本地的Graph中,以备后续创建Docker容器时的使用;
在Handle.PostImageCreate, 将下载的image交给graphdriver; 一方创建graph对象,另一方面在GraphDB中记录image之间的关系。
docker run命令执行两部分内容, 一是,创建Docker容器所需的rootfs(layered); 二是, 创建容器的网络等运行环境,并真正运行用户指令。
PostContainersCreate: graphdriver将rootfs所有镜像,加载安装至Docker容器指定的文件目录下;
PostContainersStart: libcontainer被调用,完成Docker容器内部的运行环境初始化,并最终执行用户要求启动的命令。
1. 启动Client, 主要作用是发送comment指令;
cmd docker.go
初始化client配置flag参数, 初始化命令行参数结构体; newDaemonCommand(), cmd.Execute() 包含:PreRun(), PostRun(), PersistentPostRun() 子命令的执行顺序不同;
NewDockerCli 启动Client, command.NewDockerCli()
TlsConfig对象的创建是为了保障cli在传输数据的时候,遵循安全传输层协议(TLS)。
安全传输层协议(TLS) 用于两个通信应用程序之间保密性与数据完整性,该协议有两层组成:TLS记录协议和TLS握手协议。
2. 启动Daemon
Docker Server模块接受Docker Client的请求,并在Engine中处理请求,然后根据请求类型,创建出指定的Job并运行,运行过程的作用有以下几种可能:
向Docker Registry获取镜像,通过graphdriver执行容器镜像的本地化操作,通过networkdriver执行容器网络环境的配置,通过execdriver执行容器内部运行的执行工作等。
加载Config配置, Pidfile, Mirrors, IP(配置网络环境), Context;
type Engine struct { //创建Engine调度
handlers map[string]Handler
}
type Handler func(*Job) Status //加载Job指针, 以及其状态
3. Docker Server
Docker Server最主要的功能是:接受用户通过Docker Client发送的请求,并按照相应的路由规则实现路由分发;
-> 创建Job
job := eng.Job("serveapi", flHosts...) //flHost的作用是:配置Docker Server监听的协议与监听的地址。
"serveapi", Docker Daemon 已经Register了该key 对应的func, 执行job.Run()
-> 持续服务
最后分别创建一个goroutine来执行ListenAndServe的操作。使Docker Server监听某一指定地址,接受该地址上的请求,并对以上请求路由转发至相应的处理函数Handler处。
创建路由实例:
func NewRouter() *Router {
return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
}
m := map[string]map[string]HttpApiFunc{
"GET": {
……
"/images/{name:.*}/get": getImagesGet,
……
},
"POST": {
……
"/containers/{name:.*}/copy": postContainersCopy,
},
"DELETE": {
"/containers/{name:.*}": deleteContainers,
"/images/{name:.*}": deleteImages,
},
"OPTIONS": {
"": optionsHandler,
},
}
type HttpApiFunc func(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error
创建listener监听实例:
net.Listen(proto, addr)
创建http.Server:
httpSrv := http.Server{Addr: addr, Handler: r}
启动API服务:
httpSrv.Serve(l)
4. 什么是Docker Container
从父进程fork创建子进程后, namespace主要负责命名空间的隔离; 而cgroup主要负责子进程的资源使用的限制。
在Docker Daemon, 当用户创建并启动容器时, 进行clone与隔离;
总结Docker Container的网络,可以得出4种不同的模式:bridge桥接模式、host模式、other container模式和none模式:
-> 桥接模式:
Docker通过宿主机上的网桥(docker0)来连通容器内部的网络栈与宿主机的网络栈,实现容器与宿主机乃至外界的网络通信。
当Docker Container需要暴露服务时,内部服务必须监听容器IP和端口号port_0,以便外界主动发起访问请求。由于宿主机以外的世界,
只知道宿主机eth0的网络地址,而并不知道Docker Container的IP地址,哪怕就算知道Docker Container的IP地址,从二层网络的角度来讲,
外界也无法直接通过Docker Container的IP地址访问容器内部应用。因此,Docker使用NAT方法,将容器内部的服务监听的端口与宿主机的某一个端口port_1进行“绑定”。
-> host模式, 未作网络隔离;
原文地址:https://www.cnblogs.com/ruili07/p/11002082.html
- 全球电脑手机无一幸免,英特尔CPU“漏洞事件”到底多严重?
- 评估Keras深度学习模型的性能
- Python机器学习的练习二:多元线性回归
- 熔断器 Hystrix 源码解析 —— 命令合并执行
- Python机器学习的练习一:简单线性回归
- Dubbo源码解析 —— zookeeper连接
- 浣熊检测器实例, 如何用TensorFlow的Object Detector API来训练你的物体检测器
- 用Keras进行深度学习模式的正则化方法:Dropout
- 用深度学习硬件的闲置时间,来挖比特币
- 深度学习:如何理解tensorflow文本蕴含的原理
- 重磅!腾讯与科大讯飞技术共创,Google ProtoBuf进入TARS家族!
- 深度学习与R语言
- 在Keras中展示深度学习模式的训练历史记录
- 分析漏洞利用工具包 Archie和Astrum工具包
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- PHP7创建销毁session的实例方法
- Vim如何使用相对行号实现一切操作详解
- laravel 框架执行流程与原理简单分析
- 对python自动生成接口测试的示例讲解
- 解决pip install xxx报错SyntaxError: invalid syntax的问题
- PHP如何使用JWT做Api接口身份认证的实现
- 解决python3 Pycharm上连接数据库时报错的问题
- php把文件设置为插件的技巧方法
- Python中fnmatch模块的使用详情
- tp5框架使用cookie加密算法实现登录功能示例
- python实现停车管理系统
- 浅谈Pycharm调用同级目录下的py脚本bug
- Python中logging.NullHandler 的使用教程
- Python中利用aiohttp制作异步爬虫及简单应用
- Linux内核设备驱动之系统调用笔记整理