docker 源碼分析NewDaemon 函數

NewDaemon函數是Daemon初始化時的重要函數,該函數作好了daemon處理消息的準備linux

    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 ,沒有就新建一個docker

    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  遷移metadatajson


    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)  // 建立處理系統信號的通道和協程windows

相關文章
相關標籤/搜索