docker 源码分析 三(基于1.8.2版本),NewDaemon启动
本文来分析一下New Daemon的启动过程;在daemon/daemon.go文件中;
func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {
setDefaultMtu(config) //设置默认的MTU,这里的默认值时1500
// Ensure we have compatible configuration options
if err := checkConfigOptions(config); err != nil {
return nil, err
} //检查是否出现有冲突的配置,主要有(1)config.Bridge.Iface 与 config.Bridge.IP 这两项配置不能都有,设置一个就可;
//(2) config.Bridge.EnableIPTables 与 config.Bridge.InterContainerCommunication,后者是icc,表示docker容器间是否可以互相通信,
// icc是通过iptables来实现的,即在iptables的FORWARD链中增加规则,所以不能在两者同时为false,但不清楚icc=true,但EntableIPTables为false的时候会怎么样;
// (3) 当config.Bridge.EnableIPTables为false时,config.Bridge.EnableIPMasq,ip伪装功能不能为true,和(2) 一样,因为ip伪装是通过iptables来实现的;
// Do we have a disabled network?
config.DisableBridge = isBridgeNetworkDisabled(config) // 判断config.Bridge.Iface 与 disableNetworkBridge是否相等,犹豫Iface默认值为空,disableNetworkBridge默认值为none,所以这个config.DisableBridge 为false
// Verify the platform is supported as a daemon
if !platformSupported {
return nil, ErrSystemNotSupported
} //在非 linux,freebsd,windows三种os下,这个取为false;
// Validate platform-specific requirements
if err := checkSystem(); err != nil {
return nil, err
} //checkSystem主要验证运行docker的进程是否为root,需要root权限;还有包括验证linux kernel的版本;
// set up SIGUSR1 handler on Unix-like systems, or a Win32 global event
// on Windows to dump Go routine stacks
setupDumpStackTrap() // 用来接收SIGUSR1信号,接收到信号后,将堆栈信息打印出来;通过标准库中signal.Notify()函数来实现;
// get the canonical path to the Docker root directory
var realRoot string
if _, err := os.Stat(config.Root); err != nil && os.IsNotExist(err) {
realRoot = config.Root
} else {
realRoot, err = fileutils.ReadSymlinkedDirectory(config.Root)
if err != nil {
return nil, fmt.Errorf("Unable to get the full path to root (%s): %s", config.Root, err)
}
} //获取docker运行时的根路径,后续的流程会在这个根目录下创建各种子目录,默认的是在"/var/lib/docker"路径下;
config.Root = realRoot
// Create the root directory if it doesn't exists
if err := system.MkdirAll(config.Root, 0700); err != nil {
return nil, err
} //如果根路径不存在,那么建立一个;
// set up the tmpDir to use a canonical path
tmp, err := tempDir(config.Root)
if err != nil {
return nil, fmt.Errorf("Unable to get the TempDir under %s: %s", config.Root, err)
}
realTmp, err := fileutils.ReadSymlinkedDirectory(tmp)
if err != nil {
return nil, fmt.Errorf("Unable to get the full path to the TempDir (%s): %s", tmp, err)
}
os.Setenv("TMPDIR", realTmp) //建立temp文件的存放路径,读取环境变量DOCKER_TMPDIR值,如果没有那么直接在根路径下建立tmp子目录 ,即/var/lib/docker/tmp
// Set the default driver
graphdriver.DefaultDriver = config.GraphDriver //设立graph driver,graphdriver主要是来管理镜像,以及镜像与镜像之间关系的实现方法。
// Load storage driver
driver, err := graphdriver.New(config.Root, config.GraphOptions)
if err != nil {
return nil, fmt.Errorf("error initializing graphdriver: %v", err)
}
logrus.Debugf("Using graph driver %s", driver)
//设立graph driver,graphdriver主要是来管理镜像,以及镜像与镜像之间关系的实现方法。由于config.GraphDriver的默认值为空,所以主要的处理流程在graphdriver.New()中;
//加载的优先级的顺序为 priority = []string{"aufs","btrfs","zfs","devicemapper","overlay","vfs"},
d := &Daemon{}
d.driver = driver
// Ensure the graph driver is shutdown at a later point
defer func() {
if err != nil {
if err := d.Shutdown(); err != nil {
logrus.Error(err)
}
}
}()
// Verify logging driver type
if config.LogConfig.Type != "none" {
if _, err := logger.GetLogDriver(config.LogConfig.Type); err != nil {
return nil, fmt.Errorf("error finding the logging driver: %v", err)
}
} //进行log driver的配置,默认的log driver 是json-file, 在deamon/logger 目录下是各种log driver,包括: fluentd,syslogd,journald, gelf等(前三种了解,gelf不太知道 https://www.graylog.org/resources/gelf/)
logrus.Debugf("Using default logging driver %s", config.LogConfig.Type)
// Configure and validate the kernels security support
if err := configureKernelSecuritySupport(config, d.driver.String()); err != nil {
return nil, err
} //设置系统是否使用SELinux,SElinux有个问题是不能和btrfs的graphdriver一起使用;
daemonRepo := filepath.Join(config.Root, "containers")
if err := system.MkdirAll(daemonRepo, 0700); err != nil {
return nil, err //创建容器的存储目录,在根目录下创建container子目录,/var/log/docker/container
// Migrate the container if it is aufs and aufs is enabled
if err := migrateIfDownlevel(d.driver, config.Root); err != nil {
return nil, err
} // 将可能存在的老版本docker中image和container的存储形式迁移到新版本的docker中的存储形式;
logrus.Debug("Creating images graph")
g, err := graph.NewGraph(filepath.Join(config.Root, "graph"), d.driver)
if err != nil {
return nil, err
} //使用driver实例化一个NewGraph对象,这个管理文件系统的镜像 以及 文件系统之间的关系;
// Configure the volumes driver
volStore, err := configureVolumes(config)
if err != nil {
return nil, err
} //设置数据卷driver,数据卷是docker容器之间进行数据共享的一种手段;数据卷可以是一个本机命令(通过-v 标识挂载在到容器的某个目录下)
//数据卷也可以作为数据卷容器,通过--volumes-from挂载到某个容器中;
trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)
if err != nil {
return nil, err
} //创建key,路径在/etc/docker/key.json
trustDir := filepath.Join(config.Root, "trust")
if err := system.MkdirAll(trustDir, 0700); err != nil {
return nil, err
}
trustService, err := trust.NewStore(trustDir)
if err != nil {
return nil, fmt.Errorf("could not create trust store: %s", err)
} // 创建trustService ,用于提供验证服务;
eventsService := events.New()
logrus.Debug("Creating repository list")
tagCfg := &graph.TagStoreConfig{
Graph: g,
Key: trustKey,
Registry: registryService,
Events: eventsService,
Trust: trustService,
}
repositories, err := graph.NewTagStore(filepath.Join(config.Root, "repositories-"+d.driver.String()), tagCfg)
if err != nil {
return nil, fmt.Errorf("Couldn't create Tag store repositories-%s: %s", d.driver.String(), err)
} //TagStore是用来存储镜像的仓库列表,
if restorer, ok := d.driver.(graphdriver.ImageRestorer); ok {
if _, err := restorer.RestoreCustomImages(repositories, g); err != nil {
return nil, fmt.Errorf("Couldn't restore custom images: %s", err)
}
}
d.netController, err = initNetworkController(config)
if err != nil {
return nil, fmt.Errorf("Error initializing network controller: %v", err)
} //初始化docker网络环境;
graphdbPath := filepath.Join(config.Root, "linkgraph.db")
graph, err := graphdb.NewSqliteConn(graphdbPath)
if err != nil {
return nil, err
} //graphdb是一个图数据,纪录的是镜像与镜像之间的关系;
d.containerGraph = graph
var sysInitPath string
if config.ExecDriver == "lxc" {
initPath, err := configureSysInit(config)
if err != nil {
return nil, err
}
sysInitPath = initPath
}
sysInfo := sysinfo.New(false)
// Check if Devices cgroup is mounted, it is hard requirement for container security,
// on Linux/FreeBSD.
if runtime.GOOS != "windows" && !sysInfo.CgroupDevicesEnabled {
return nil, fmt.Errorf("Devices cgroup isn't mounted")
}
ed, err := execdrivers.NewDriver(config.ExecDriver, config.ExecOptions, config.ExecRoot, config.Root, sysInitPath, sysInfo)
if err != nil {
return nil, err
} // execdriver 是使用docker容器的执行驱动,由execdriver执行容器的创建和运行等,通过调用cgroup,usernamespace等等实现;
d.ID = trustKey.PublicKey().KeyID()
d.repository = daemonRepo
d.containers = &contStore{s: make(map[string]*Container)}
d.execCommands = newExecStore()
d.graph = g
d.repositories = repositories
d.idIndex = truncindex.NewTruncIndex([]string{})
d.config = config
d.sysInitPath = sysInitPath
d.execDriver = ed
d.statsCollector = newStatsCollector(1 * time.Second)
d.defaultLogConfig = config.LogConfig
d.RegistryService = registryService
d.EventsService = eventsService
d.volumes = volStore
d.root = config.Root
go d.execCommandGC()
if err := d.restore(); err != nil {
return nil, err
}
return d, nil
}
docker 源码分析 三(基于1.8.2版本),NewDaemon启动的更多相关文章
- docker 源码分析 四(基于1.8.2版本),Docker镜像的获取和存储
前段时间一直忙些其他事情,docker源码分析的事情耽搁了,今天接着写,上一章了解了docker client 和 docker daemon(会启动一个http server)是C/S的结构,cli ...
- docker 源码分析 一(基于1.8.2版本),docker daemon启动过程;
最近在研究golang,也学习一下比较火的开源项目docker的源代码,国内比较出名的docker源码分析是孙宏亮大牛写的一系列文章,但是基于的docker版本有点老:索性自己就git 了一下最新的代 ...
- Docker源码分析(三):Docker Daemon启动
1 前言 Docker诞生以来,便引领了轻量级虚拟化容器领域的技术热潮.在这一潮流下,Google.IBM.Redhat等业界翘楚纷纷加入Docker阵营.虽然目前Docker仍然主要基于Linux平 ...
- Docker源码分析(八):Docker Container网络(下)
1.Docker Client配置容器网络模式 Docker目前支持4种网络模式,分别是bridge.host.container.none,Docker开发者可以根据自己的需求来确定最适合自己应用场 ...
- Docker源码分析(五):Docker Server的创建
1.Docker Server简介 Docker架构中,Docker Server是Docker Daemon的重要组成部分.Docker Server最主要的功能是:接受用户通过Docker Cli ...
- Docker源码分析(一):Docker架构
1 背景 1.1 Docker简介 Docker是Docker公司开源的一个基于轻量级虚拟化技术的容器引擎项目,整个项目基于Go语言开发,并遵从Apache 2.0协议.目前,Docker可以在容器内 ...
- 转载:Docker源码分析(一):Docker架构
原文地址: http://www.infoq.com/cn/articles/docker-source-code-analysis-part1 作者:孙宏亮 1 背景 1.1 Docker简介 D ...
- Docker源码分析(九):Docker镜像
1.前言 回首过去的2014年,大家可以看到Docker在全球刮起了一阵又一阵的“容器风”,工业界对Docker的探索与实践更是一波高过一波.在如今的2015年以及未来,Docker似乎并不会像其他昙 ...
- Docker源码分析(七):Docker Container网络 (上)
1.前言(什么是Docker Container) 如今,Docker技术大行其道,大家在尝试以及玩转Docker的同时,肯定离不开一个概念,那就是“容器”或者“Docker Container”.那 ...
随机推荐
- forever让nodejs应用后台执行
nodejs一般是当成一条用户命令执行的,当用户断开客户连接,运用也就停了,很烦人.如何让nodejs应用当成服务,在后台执行呢? 最简单的办法: $ nohup node app.js & ...
- SPSS数据分析—Probit回归模型
Probit含义为概率单位,和Logistic回归一样,Probit回归也用于因变量为分类变量的情况,通常情况下,两种回归方法的结果非常接近,但是由于Probit回归的结果解释起来比较抽象不易理解,因 ...
- web storage和cookie的区别
Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的.Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外co ...
- Asp.net的request类
ASP.NET获取客户端信息,暂时就这几个,有待添加~~ 1. 在ASP.NET中专用属性: 获取服务器电脑名:Page.Server.ManchineName 获取用户信息:Page.User 获取 ...
- 关于app的具体实施
鉴于我们小组做的app是关于在线做题和游戏相融合的,所以,我会先学习UI设计,毕竟好的UI设计不仅会给用户耳目一新的体验,同时还会让用户愿意去包容一些小BUG,但如果你的软件做的非常好,功能提供的很全 ...
- MVC中获取来自控制器名称与动作的方法
#region 获取控制器名称与动作 protected void GetNameSpace() { var nameSpace = this.RouteData.Values["contr ...
- javascript中对象在OOP方面的一些知识(主要是prototype和__proto__相关)
在ES6的Class到来之前,先总结下个人对js中prototype属性的理解. 1.构造函数(大写函数名 this 无return) 2.原型对象(函数.prototype) 3.实例对象( ...
- C#中的@符号用法
C#中的@符号其实有很多的用法,我们来看看@有什么神奇之处. 1.限定字符串 用 @ 符号加在字符串前面表示其中的转义字符“不”被处理. 如果我们写一个文件的路径,例如"D:/文本文件&qu ...
- 对COM 组件的调用返回了错误 HRESULT E_FAIL
.net ppt转pdf时报以下错误: 对COM 组件的调用返回了错误 HRESULT E_FAIL 在服务器端打开PPT,选项--另存为--PDF,发现PowerPoint报了个错误: “无法找到打 ...
- 如何更换centos6源
1.wget http://mirrors.163.com/.help/CentOS6-Base-163.repo 2.根据教程:http://mirrors.163.com/.help/centos ...