docker 源碼分析 三(基於1.8.2版本),NewDaemon啓動

本文來分析一下New Daemon的啓動過程;在daemon/daemon.go文件中;linux

func NewDaemon(config *Config, registryService *registry.Service) (daemon *Daemon, err error) {docker

    setDefaultMtu(config)    //設置默認的MTU,這裏的默認值時1500json

 

    // Ensure we have compatible configuration optionswindows

    if err := checkConfigOptions(config); err != nil {api

        return nil, err網絡

    }                               //檢查是否出現有衝突的配置,主要有(1)config.Bridge.Iface 與 config.Bridge.IP 這兩項配置不能都有,設置一個就可;app

                                     //(2) config.Bridge.EnableIPTables 與 config.Bridge.InterContainerCommunication,後者是icc,表示docker容器間是否能夠互相通訊,函數

                                     // icc是經過iptables來實現的,即在iptables的FORWARD鏈中增長規則,因此不能在二者同時爲false,但不清楚icc=true,但EntableIPTables爲false的時候會怎麼樣;ui

                                     // (3) 當config.Bridge.EnableIPTables爲false時,config.Bridge.EnableIPMasq,ip假裝功能不能爲true,和(2) 同樣,由於ip假裝是經過iptables來實現的;spa

 

    // 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}

相關文章
相關標籤/搜索