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