docker 源码分析NewDaemon 函数

NewDaemon函数是Daemon初始化时的重要函数,该函数做好了daemon处理消息的准备

    setDefaultMtu(config)  //  设置默认MTU 1500
    ModifyRootKeyLimit() //  "/proc/sys/kernel/keys/root_maxkeys"  key权限不足的话修改权限
    verifyDaemonSettings(config) //   检查配置是否正确,不正确退出
    config.DisableBridge = isBridgeNetworkDisabled(config)   // conf.BridgeConfig.Iface == config.DisableNetworkBridge

    if !platformSupported {  //   系统是否支持
        return nil, errSystemNotSupported
    }

    checkSystem()  //   检查系统版本等信息

    uidMaps, gidMaps, err := setupRemappedRoot(config)  // pkg/idtools/idtools.go  根据username、groupname创建两个map
    rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) // pkg/idtools/idtools.go 创建根uid、gid

    setupDaemonProcess(config)   // linux   设置 /proc/self/oom_score_adj
    tmp, err := tempDir(config.Root, rootUID, rootGID)  //  创建tmp文件夹
    realTmp, err := fileutils.ReadSymlinkedDirectory(tmp)  //  pkg/fileutils/fileutils.go 给tmp创建一个symlink
    os.Setenv("TMPDIR", realTmp)

    d := &Daemon{configStore: config}   //创建个daem 实例
    defer func() {  // 函数退出时 daemon 关闭
        if err != nil {
            if err := d.Shutdown(); err != nil {
                logrus.Error(err)
            }
        }
    }()

    d.setupSeccompProfile()  // 需要的话创建 seccompProfile
    d.setDefaultIsolation()  // 只是windows使用,决定 isolation mode

    configureMaxThreads(config)  // linux 下面设置最大线程 /proc/sys/kernel/threads-max
    ensureDefaultAppArmorProfile()  // 如果使能 AppArmor ,则加载

    daemonRepo := filepath.Join(config.Root, "containers")   // 创建一个containers的目录
    if err := idtools.MkdirAllAs(daemonRepo, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
        return nil, err
    }

    if runtime.GOOS == "windows" {   //  windows创建credentialspecs的目录
        if err := system.MkdirAll(filepath.Join(config.Root, "credentialspecs"), 0); err != nil && !os.IsExist(err) {
            return nil, err
        }
    }

    driverName := os.Getenv("DOCKER_DRIVER")   // 取环境变量设置值,未设置取配置
    if driverName == "" {
        driverName = config.GraphDriver
    }

    d.RegistryService = registryService
    d.PluginStore = plugin.NewStore(config.Root) // todo: remove
    // Plugin system initialization should happen before restore. Do not change order.
    d.pluginManager, err = plugin.NewManager(plugin.ManagerConfig{   // plugin/manager.go  创建plugin manager 实例
        Root:               filepath.Join(config.Root, "plugins"),
        ExecRoot:           getPluginExecRoot(config.Root),
        Store:              d.PluginStore,
        Executor:           containerdRemote,
        RegistryService:    registryService,
        LiveRestoreEnabled: config.LiveRestoreEnabled,
        LogPluginEvent:     d.LogPluginEvent, // todo: make private
    })

    d.layerStore, err = layer.NewStoreFromOptions(layer.StoreOptions{   // lay/layer_store.go 创建graphDriver实例,从driver创建layer仓库的实例
        StorePath:                 config.Root,
        MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
        GraphDriver:               driverName,
        GraphDriverOptions:        config.GraphOptions,
        UIDMaps:                   uidMaps,
        GIDMaps:                   gidMaps,
        PluginGetter:              d.PluginStore,
        ExperimentalEnabled:       config.Experimental,
    })

    graphDriver := d.layerStore.DriverName()   // 取layer里面的graphDriver
    imageRoot := filepath.Join(config.Root, "image", graphDriver) 


    configureKernelSecuritySupport(config, graphDriver)  // linux内核安全支持的配置
    d.downloadManager = xfer.NewLayerDownloadManager(d.layerStore, *config.MaxConcurrentDownloads)   // distribution/xfer/download.go 创建层下载管理实例
    d.uploadManager = xfer.NewLayerUploadManager(*config.MaxConcurrentUploads)  // distribution/xfer/upload.go 创建层上传管理实例
    ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb"))   // image/fs.go   创建仓库后端的文件系统
    d.imageStore, err = image.NewImageStore(ifs, d.layerStore)  // image/store.go  创建镜像仓库实例
    volStore, err := d.configureVolumes(rootUID, rootGID) // 创建 volumes driver实例
    trustKey, err := api.LoadOrCreateTrustKey(config.TrustKeyPath)  //  api/common.go 按照路径加载libtrust key ,没有就新建一个

    trustDir := filepath.Join(config.Root, "trust")
    system.MkdirAll(trustDir, 0700)
    distributionMetadataStore, err := dmetadata.NewFSMetadataStore(filepath.Join(imageRoot, "distribution"))  // distribution/metadata/metadata.go  按照路径创建一个基于文件系统的元数据仓库实例

    eventsService := events.New()   //  daemon/events/events.go  创建event服务实例
    referenceStore, err := refstore.NewReferenceStore(filepath.Join(imageRoot, "repositories.json"))  // reference/store.go  按照路径创建 reference仓库实例

    v1.Migrate(config.Root, graphDriver, d.layerStore, d.imageStore, referenceStore, distributionMetadataStore) // migrate/v1/migrate.go  迁移metadata


    d.initDiscovery(config) // 创建 discoveryWatcher 实例

    sysInfo := sysinfo.New(false)   // 获取系统信息,linux 不支持cgroup则返回
    if runtime.GOOS == "linux" && !sysInfo.CgroupDevicesEnabled {
        return nil, errors.New("Devices cgroup isn't mounted")
    }

    d.ID = trustKey.PublicKey().KeyID()  // 赋值
    d.repository = daemonRepo
    d.containers = container.NewMemoryStore()
    d.execCommands = exec.NewStore()
    d.referenceStore = referenceStore
    d.distributionMetadataStore = distributionMetadataStore
    d.trustKey = trustKey
    d.idIndex = truncindex.NewTruncIndex([]string{})
    d.statsCollector = d.newStatsCollector(1 * time.Second)
    d.defaultLogConfig = containertypes.LogConfig{
        Type:   config.LogConfig.Type,
        Config: config.LogConfig.Config,
    }
    d.EventsService = eventsService
    d.volumes = volStore
    d.root = config.Root
    d.uidMaps = uidMaps
    d.gidMaps = gidMaps
    d.seccompEnabled = sysInfo.Seccomp
    d.apparmorEnabled = sysInfo.AppArmor
    d.nameIndex = registrar.NewRegistrar()
    d.linkIndex = newLinkIndex()
    d.containerdRemote = containerdRemote

    go d.execCommandGC()  // 新建协程清理容器不需要的命令

    d.containerd, err = containerdRemote.Client(d) //  创建和daemon相关的容器客户端 libcontainerd
    d.restore()    //  restart  container

    // FIXME: this method never returns an error
    info, _ := d.SystemInfo()   // 获取host server系统信息

    engineVersion.WithValues(
        dockerversion.Version,
        dockerversion.GitCommit,
        info.Architecture,
        info.Driver,
        info.KernelVersion,
        info.OperatingSystem,
    ).Set(1)
    engineCpus.Set(float64(info.NCPU))
    engineMemory.Set(float64(info.MemTotal))

    // set up SIGUSR1 handler on Unix-like systems, or a Win32 global event
    // on Windows to dump Go routine stacks
    stackDumpDir := config.Root
    if execRoot := config.GetExecRoot(); execRoot != "" {
        stackDumpDir = execRoot
    }
    d.setupDumpStackTrap(stackDumpDir)  // 创建处理系统信号的通道和协程

posted on 2017-03-26 22:16  arwen_spy  阅读(641)  评论(0编辑  收藏  举报

导航