成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Docker 深入篇之 Build 原理

BearyChat / 1514人閱讀

摘要:先簡(jiǎn)單介紹下,通常情況下我們將其稱之為鏡像,鏡像是由多個(gè)層組成的文件,這些層用于在容器內(nèi)執(zhí)行代碼命令等。而的時(shí)候則會(huì)將此信息再次進(jìn)行編碼。

使用 Docker 時(shí),最常用的命令無(wú)非是 docker containerdocker image 相關(guān)的子命令,當(dāng)然最初沒(méi)有管理類命令(或者說(shuō)分組)的時(shí)候,最常使用的命令也無(wú)非是 docker run docker commit docker builddocker images 這些。

今天來(lái)聊一下和 Docker 中核心概念 image 相關(guān)的重要命令, docker build 或者說(shuō) docker image build 為了簡(jiǎn)便起見(jiàn),下文的命令全部使用 docker build 。

Docker Image

先簡(jiǎn)單介紹下 Docker Image, 通常情況下我們將其稱之為鏡像,鏡像是由多個(gè)層組成的文件,這些層用于在容器內(nèi)執(zhí)行代碼(命令)等。每個(gè)鏡像基本上都是根據(jù)應(yīng)用程序完整的可執(zhí)行版本進(jìn)行構(gòu)建的,并且需要注意的是,它會(huì)依賴于主機(jī)的系統(tǒng)內(nèi)核。當(dāng)用戶在運(yùn)行鏡像時(shí),這將會(huì)創(chuàng)建一個(gè)或者多個(gè)容器實(shí)例。

Dockerd

Dockerd 是 Docker 的服務(wù)端,默認(rèn)情況下提供 Unix Domain Socket 連接,當(dāng)然也可以監(jiān)聽(tīng)某個(gè)端口,用于對(duì)外提供服務(wù)。 所以有時(shí)候,我們也可以使用服務(wù)器上的 Docker daemon 來(lái)提供服務(wù),以加快構(gòu)建速度及解決一些網(wǎng)絡(luò)問(wèn)題之類的。

好的,基礎(chǔ)概念了解了, 那我們開始進(jìn)入正題。

使用 Dockerfile

我們知道構(gòu)建鏡像的方法有多種,本文中我們只介紹使用 Dockerfile 通過(guò) docker build 的方式構(gòu)建鏡像。

為了簡(jiǎn)便,我們以一個(gè)簡(jiǎn)單的 Dockerfile 開始。構(gòu)建一個(gè)容器內(nèi)使用的 kubectl 工具 (當(dāng)然選擇它的原因在于 kubectl 足夠大,并不考慮可用性,這個(gè)稍后解釋)

FROM scratch

LABEL maintainer="Jintao Zhang "

ADD kubectl /kubectl
ENTRYPOINT [ "/kubectl" ]

Dockerfile 足夠簡(jiǎn)單,只是將 kubectl 的二進(jìn)制文件拷貝進(jìn)去,并將 Entrypoint 設(shè)置為 kubectl 。

Dockerd in Docker

我個(gè)人一般為了避免環(huán)境的污染,大多數(shù)的事情都在容器內(nèi)完成。包括 dockerd 我也啟在容器內(nèi)。其中的原理不再介紹,可以參考我之前的文章或分享。使用起來(lái)很簡(jiǎn)單:

docker run --privileged -d -P docker:stable-dind

注意這里使用了 -P 所以本地會(huì)隨機(jī)映射一個(gè)端口,當(dāng)然你也可以直接指定映射到容器內(nèi)的 2375 端口。

(Tao) ?  build git:(master) docker ps                                                       
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                     NAMES
b56f6483614d        docker:stable-dind          "dockerd-entrypoint.…"   9 hours ago         Up 9 hours          0.0.0.0:32769->2375/tcp   trusting_babbage
構(gòu)建

我們直接使用啟動(dòng)在容器內(nèi)的 dockerd 進(jìn)行構(gòu)建,通過(guò)上面的 docker ps 命令可以看到是映射到了本地的 32769 端口。所以我們使用以下命令進(jìn)行構(gòu)建:

(Tao) ?  kubectl git:(master) docker -H 0.0.0.0:32769 images                                                              
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE                                      
(Tao) ?  kubectl git:(master) docker -H 0.0.0.0:32769 build -t local/kubectl .                                            
Sending build context to Docker daemon  55.09MB
Step 1/4 : FROM scratch
 --->
Step 2/4 : LABEL maintainer="Jintao Zhang "
 ---> Running in ebcf44071bf0
Removing intermediate container ebcf44071bf0
 ---> eb4ea1725ff2
Step 3/4 : ADD kubectl /kubectl
 ---> 1aad06c4dbb4
Step 4/4 : ENTRYPOINT [ "/kubectl" ]
 ---> Running in 2fc78fe974e3
Removing intermediate container 2fc78fe974e3
 ---> 457802d4bf3e
Successfully built 457802d4bf3e
Successfully tagged local/kubectl:latest
(Tao) ?  kubectl git:(master) docker -H 0.0.0.0:32769 images                  
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
local/kubectl       latest              457802d4bf3e        3 seconds ago       55.1MB

看日志及結(jié)果,可以看到我們已經(jīng)成功的構(gòu)建了我們所需的鏡像。說(shuō)了這么多,其實(shí)我們今天的內(nèi)容才剛剛開始。

深入原理 Dockerd 服務(wù)

在本文一開始,我已經(jīng)提過(guò) Dockerd 是 Docker 的后端服務(wù),通過(guò)上面的

docker -H 0.0.0.0:32769 images                                                              

這條命令可以看到我們通過(guò) -H 指定了本地 32679 端口的 dockerd 服務(wù),這其實(shí)是個(gè) HTTP 服務(wù),我們來(lái)驗(yàn)證下。

(Tao) ?  kubectl git:(master) curl -i   0.0.0.0:32769/_ping
HTTP/1.1 200 OK
Api-Version: 1.37
Docker-Experimental: false
Ostype: linux
Server: Docker/18.03.1-ce (linux)
Date: Tue, 04 Sep 2018 17:20:51 GMT
Content-Length: 2
Content-Type: text/plain; charset=utf-8

OK%                  

可以看到幾條關(guān)鍵的信息 Api-Version: 1.37 這個(gè)表明了當(dāng)前使用的 API 版本,本文的內(nèi)容也是以 1.37 為例進(jìn)行介紹,這是當(dāng)前的穩(wěn)定版本。我們也可以通過(guò) docker version 進(jìn)行查看。

(Tao) ?  kubectl git:(master) docker -H 0.0.0.0:32769 version                                                             
Client:
 Version:           18.06.0-ce
 API version:       1.37 (downgraded from 1.38)
 Go version:        go1.10.3
 Git commit:        0ffa825
 Built:             Wed Jul 18 19:11:45 2018
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          18.03.1-ce
  API version:      1.37 (minimum version 1.12)
  Go version:       go1.9.5
  Git commit:       9ee9f40
  Built:            Thu Apr 26 07:23:03 2018
  OS/Arch:          linux/amd64
  Experimental:     false

可以看到我本地在用的 docker cli 版本較高,當(dāng)連接到低版本的 dockerd 時(shí),API 版本降級(jí)至與 dockerd 版本保持一致。

當(dāng)然,你可能會(huì)問(wèn),如果是 dockerd 版本高會(huì)如何呢?其實(shí)我日常中的開發(fā)環(huán)境就是這樣,大多數(shù) API 都沒(méi)什么影響, 不過(guò)這并不是今天的重點(diǎn)。

root@bdcdac73ee20:/# docker version
Client:
 Version:      17.06.0-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:15:15 2017
 OS/Arch:      linux/amd64

Server:
 Version:      dev
 API version:  1.39 (minimum version 1.12)
 Go version:   go1.10.3
 Git commit:   e8cc5a0b3
 Built:        Tue Sep  4 10:00:36 2018
 OS/Arch:      linux/amd64
 Experimental: false
build context

回到我們上面的構(gòu)建過(guò)程中。我們可以看到日志內(nèi)容的第一行:

...
Sending build context to Docker daemon  55.09MB

從這條日志,我們可以得到兩個(gè)信息:

構(gòu)建的過(guò)程是將 build context 發(fā)送給 dockerd , 實(shí)際的構(gòu)建壓力在 dockerd 上

發(fā)送了 55.09 MB

第一條結(jié)論,我們?cè)谏弦恍」?jié)已經(jīng)討論過(guò)了,我們來(lái)重點(diǎn)看下第二條結(jié)論。

(Tao) ?  kubectl git:(master) ls -al 
總用量 53808
drwxrwxr-x. 2 tao tao     4096 9月   5 01:00 .
drwxrwxr-x. 3 tao tao     4096 9月   5 00:57 ..
-rw-rw-r--. 1 tao tao      109 9月   5 01:00 Dockerfile
-rwxrwxr-x. 1 tao tao 55084063 9月   5 00:53 kubectl
(Tao) ?  kubectl git:(master) du -sh .
53M     .
(Tao) ?  kubectl git:(master) du -sh kubectl Dockerfile 
53M     kubectl
4.0K    Dockerfile

按照我們 Dockerfile 的內(nèi)容,我們需要將 kubectl 的二進(jìn)制包放入鏡像內(nèi),所以 build context 雖然比二進(jìn)制文件多出來(lái) 2M 左右的大小你也不會(huì)很意外。

但我這里做了另一個(gè)例子,不多贅述,代碼可以在我的 [GitHub]() 中找到。這里貼出來(lái)結(jié)果:

(Tao) ?  text git:(master) ls -al                                                                                          
總用量 16                                                                                                                  
drwxrwxr-x. 2 tao tao 4096 9月   5 01:45 .                                                                                
drwxrwxr-x. 4 tao tao 4096 9月   5 01:44 ..                             
-rw-rw-r--. 1 tao tao   77 9月   5 01:45 Dockerfile                       
-rw-rw-r--. 1 tao tao   61 9月   5 01:45 file  
(Tao) ?  text git:(master) du -b Dockerfile file
77      Dockerfile
61      file                                                                                                              
(Tao) ?  text git:(master) docker -H 0.0.0.0:32769 build --no-cache=true -t local/file .                                  
Sending build context to Docker daemon  3.072kB
...

相信你看到這個(gè)結(jié)果已經(jīng)明白我想表達(dá)的意思,我們繼續(xù)探索下這個(gè)過(guò)程。

/build 請(qǐng)求

前面我們已經(jīng)說(shuō)過(guò),這就是個(gè)普通的 HTTP 請(qǐng)求,所以我們當(dāng)然可以直接抓包來(lái)看看到底發(fā)生了什么?

很簡(jiǎn)單,通過(guò) dockerd 的地址,使用 POST 方法,訪問(wèn) /build 接口, 當(dāng)然實(shí)際情況是會(huì)增加前綴,即我在上面提到的版本號(hào),在目前的環(huán)境中使用的是 /v1.37/build 這個(gè)接口。

而這個(gè)請(qǐng)求攜帶了一些很有用的參數(shù),和頭信息。這里我來(lái)簡(jiǎn)單說(shuō)下:

Header

build 請(qǐng)求的頭部,主要有以下兩個(gè)

Content-Type 默認(rèn)值為 application/x-tar,表明自己是一個(gè)歸檔。

X-Registry-Config 這個(gè)頭部信息中包含著 registry 的地址及認(rèn)證信息,并且以 base64 進(jìn)行編碼。對(duì) docker 熟悉的朋友或者看過(guò)我之前文章的朋友應(yīng)該知道, Docker cli 在 login 成功后,會(huì)將認(rèn)證信息保存至本地,密碼做 base64 保存。而 build 的時(shí)候則會(huì)將此信息再次 base64 進(jìn)行編碼。通過(guò)這里也可以看出來(lái),在使用遠(yuǎn)端 Dockerd 的時(shí)候, 應(yīng)該盡量配置 TLS 以防止中間人攻擊,造成密碼泄漏等情況。

Parameters

請(qǐng)求參數(shù)中,列幾個(gè)比較有意義的:

t 這其實(shí)就是我們 docker build -t 時(shí)候指定的參數(shù),并且,我們可以同時(shí)指定多個(gè) -t 同時(shí)構(gòu)建多個(gè)不同名稱的鏡像。

memory cpusetcpus 這些主要用于資源限制

buildargs 如果想要了解這個(gè)參數(shù),可以回憶下 Dockerfile 中的 ARG 指令的用法

當(dāng)然,我們想要探索的過(guò)程其實(shí)重點(diǎn)就在于請(qǐng)求頭部了, 整個(gè)請(qǐng)求的輸入流,必須是一個(gè) tar 壓縮包,并且支持 identity (不壓縮), gzip, bzip2, xz 等壓縮算法。

實(shí)現(xiàn)

我們來(lái)看下基本的實(shí)現(xiàn):

func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, options types.ImageBuildOptions) (types.ImageBuildResponse, error) {
    query, err := cli.imageBuildOptionsToQuery(options)
    if err != nil {
        return types.ImageBuildResponse{}, err
    }

    headers := http.Header(make(map[string][]string))
    buf, err := json.Marshal(options.AuthConfigs)
    if err != nil {
        return types.ImageBuildResponse{}, err
    }
    headers.Add("X-Registry-Config", base64.URLEncoding.EncodeToString(buf))

    headers.Set("Content-Type", "application/x-tar")

    serverResp, err := cli.postRaw(ctx, "/build", query, buildContext, headers)
    if err != nil {
        return types.ImageBuildResponse{}, err
    }

    osType := getDockerOS(serverResp.header.Get("Server"))

    return types.ImageBuildResponse{
        Body:   serverResp.body,
        OSType: osType,
    }, nil
}
總結(jié)

這篇主要內(nèi)容集中在 docker build 的過(guò)程及其原理上,為什么首先要寫這篇,主要是因?yàn)殓R像和我們息息相關(guān), 并且也是我們使用的第一步。而很多情況下,推進(jìn)業(yè)務(wù)容器化也都要面臨著性能優(yōu)化及其他規(guī)范之類的。

其實(shí)關(guān)于 build 的細(xì)節(jié)還有很多,如果有空,我就再更新下一篇。


可以通過(guò)下面二維碼訂閱我的文章公眾號(hào)【MoeLove】

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/27433.html

相關(guān)文章

  • Docker 深入篇之 Build 原理

    摘要:先簡(jiǎn)單介紹下,通常情況下我們將其稱之為鏡像,鏡像是由多個(gè)層組成的文件,這些層用于在容器內(nèi)執(zhí)行代碼命令等。而的時(shí)候則會(huì)將此信息再次進(jìn)行編碼。 使用 Docker 時(shí),最常用的命令無(wú)非是 docker container 和 docker image 相關(guān)的子命令,當(dāng)然最初沒(méi)有管理類命令(或者說(shuō)分組)的時(shí)候,最常使用的命令也無(wú)非是 docker run docker commit dock...

    scq000 評(píng)論0 收藏0
  • 前端工程化篇之 Gulp

    摘要:是一個(gè)構(gòu)建工具,基于的平臺(tái)運(yùn)行,使用的是的模塊化語(yǔ)法。我們使用需要用到的包一個(gè)任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯對(duì)應(yīng)的是同步任務(wù),從左到右,依次執(zhí)行任務(wù)。時(shí)間長(zhǎng)對(duì)應(yīng)的是異步任務(wù),效率高,時(shí)間短。 gulp 是一個(gè)構(gòu)建工具,基于Node.js的平臺(tái)運(yùn)行,使用的是commonJs的模塊化語(yǔ)法。 我們使用gulp需要用到的包 一個(gè)TASK任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯、 gulp.s...

    Donald 評(píng)論0 收藏0
  • 前端工程化篇之 Gulp

    摘要:是一個(gè)構(gòu)建工具,基于的平臺(tái)運(yùn)行,使用的是的模塊化語(yǔ)法。我們使用需要用到的包一個(gè)任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯對(duì)應(yīng)的是同步任務(wù),從左到右,依次執(zhí)行任務(wù)。時(shí)間長(zhǎng)對(duì)應(yīng)的是異步任務(wù),效率高,時(shí)間短。 gulp 是一個(gè)構(gòu)建工具,基于Node.js的平臺(tái)運(yùn)行,使用的是commonJs的模塊化語(yǔ)法。 我們使用gulp需要用到的包 一個(gè)TASK任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯、 gulp.s...

    LeanCloud 評(píng)論0 收藏0
  • react-native 布局篇之flexbox

    摘要:布局直接閱讀大神文章阮一峰寫的布局。有幾個(gè)注意的點(diǎn),我在剛剛開始中總結(jié)的容器屬性,,布局方式主軸對(duì)齊方式交叉軸對(duì)齊方式這里需要特別注意的就是主軸和交叉軸。特別注意的作用對(duì)象是主軸在中設(shè)置是水平方向上占滿整個(gè)容器。 FlexBox布局 直接閱讀大神文章:阮一峰寫的FlexBox布局。在react-native中原理是一樣的,只不過(guò)可能有寫屬性在react-native中簡(jiǎn)化了。有幾個(gè)注意...

    Near_Li 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<