天天看點

docker學習 - docker rundocker run流程

通過使用者指定的鏡像名和tag,在tagstore中查找image_id,擷取image對象(本地的image json檔案裡有鏡像資訊)

檢查鏡像layer數(不超過127),鏡像層數太多會造成性能問題

将runconfig.config和image.config合并

建立{container.id}-init和container.id鏡像的目錄,在init layer建立.dockerinit、/etc/hosts、/etc/hostname等, container.id鏡像是read-write layer

将container對象持久化到path.join(container.id, “config.json”)

在daemon.idindex中注冊container.id,在daemon.contstore中記錄container.id和container對象的映射關系

通過container.id從daemon.contstore中擷取container對象

配置容器的dns位址/etc/resolv.conf

将所有祖先鏡像挂載到path.join(graphdriver.root, “mnt”, container.id)

初始化容器的hosts檔案/etc/hosts

檢查主機是否開啟cgroup記憶體限制、swap記憶體限制、ipv4轉發

将容器内挂在目錄和主控端目錄的映射關系存入container.volume

将容器的link資訊存入graphdb中,基于sqllite的圖模型的資料庫

通過iptables開啟link容器間的通信,并env化

擷取容器運作的目前目錄,擷取使用者指定的環境變量

建構execdriver的command對象,包括程序指令、network、mount、resources、workingdir,用于容器的啟動和配置

将command對象持久化到path.join(config.root, “execdriver/native/container.json”)

通過execdriver.run啟動command對象

dockerinit是daemon啟動容器運作的第一個程序,類似linux的init程序

初始化容器的network資源、mount資源、設定使用者、設定環境變量等在daemon程序中做不到事情

daemon執行流程

建立syncpipe用于跨namespace的通信

execdriver.run建立一個exec.cmd對象來執行dockerinit指令

exec.cmd.args代表dockerinit的執行參數,native表示execdriver類型,pipe表示同步管道的檔案描述符,root表示容器- 配置檔案container.json和state.json所在目錄,args表示使用者指定的指令

exec.cmd.sysprocattr攜帶需要為程序建立新namespace參數cloneflags,包括newns、newuts、newipc、newpid、newnet

調用exec.cmd.start()啟動dockerinit程序

調用namespaces.setupcgroups為dockerinit配置cgroup(cpu、iops、memory、freezer)

調用namespaces.initializenetworking為dockerinit建立網絡棧

調用syncpipe.sendtochild(networkstate)将需要dockerinit完成的剩餘網絡配置發給dockerinit

調用syncpipe.readfromchild與dockerinit同步

dockerinit執行流程

從參數中讀取root配置檔案所在目錄

從path.join(root, “container.json”)中讀取daemon傳過來的execdriver.command對象,擷取容器的配置資訊

調用mount.initializemountnamespace完成挂載資源的初始化,包括rootfs根檔案系統,挂載點volume,裝置檔案

調用namespaces.finalizenamespace完成剩餘的配置,包括關閉除0/1/2以外的檔案句柄,為容器建立新的使用者id、組id,切換到工作目錄

調用syscall.exec将容器主程序的執行權交給使用者程式