成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Docker 深入篇之 Build 原理

BearyChat / 1589人閱讀

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

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

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

Docker Image

先簡單介紹下 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)聽某個(gè)端口,用于對(duì)外提供服務(wù)。 所以有時(shí)候,我們也可以使用服務(wù)器上的 Docker daemon 來提供服務(wù),以加快構(gòu)建速度及解決一些網(wǎng)絡(luò)問題之類的。

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

使用 Dockerfile

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

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

FROM scratch

LABEL maintainer="Jintao Zhang "

ADD kubectl /kubectl
ENTRYPOINT [ "/kubectl" ]

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

Dockerd in Docker

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

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)建,通過上面的 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)建了我們所需的鏡像。說了這么多,其實(shí)我們今天的內(nèi)容才剛剛開始。

深入原理 Dockerd 服務(wù)

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

docker -H 0.0.0.0:32769 images                                                              

這條命令可以看到我們通過 -H 指定了本地 32679 端口的 dockerd 服務(wù),這其實(shí)是個(gè) HTTP 服務(wù),我們來驗(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)定版本。我們也可以通過 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ì)問,如果是 dockerd 版本高會(huì)如何呢?其實(shí)我日常中的開發(fā)環(huán)境就是這樣,大多數(shù) API 都沒什么影響, 不過這并不是今天的重點(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)建過程中。我們可以看到日志內(nèi)容的第一行:

...
Sending build context to Docker daemon  55.09MB

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

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

發(fā)送了 55.09 MB

第一條結(jié)論,我們?cè)谏弦恍」?jié)已經(jīng)討論過了,我們來重點(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)制文件多出來 2M 左右的大小你也不會(huì)很意外。

但我這里做了另一個(gè)例子,不多贅述,代碼可以在我的 [GitHub]() 中找到。這里貼出來結(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è)過程。

/build 請(qǐng)求

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

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

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

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 熟悉的朋友或者看過我之前文章的朋友應(yīng)該知道, Docker cli 在 login 成功后,會(huì)將認(rèn)證信息保存至本地,密碼做 base64 保存。而 build 的時(shí)候則會(huì)將此信息再次 base64 進(jìn)行編碼。通過這里也可以看出來,在使用遠(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)然,我們想要探索的過程其實(shí)重點(diǎn)就在于請(qǐng)求頭部了, 整個(gè)請(qǐng)求的輸入流,必須是一個(gè) tar 壓縮包,并且支持 identity (不壓縮), gzip, bzip2, xz 等壓縮算法。

實(shí)現(xiàn)

我們來看下基本的實(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 的過程及其原理上,為什么首先要寫這篇,主要是因?yàn)殓R像和我們息息相關(guān), 并且也是我們使用的第一步。而很多情況下,推進(jìn)業(yè)務(wù)容器化也都要面臨著性能優(yōu)化及其他規(guī)范之類的。

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


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

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

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

相關(guān)文章

  • Docker 深入篇之 Build 原理

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

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

    摘要:是一個(gè)構(gòu)建工具,基于的平臺(tái)運(yùn)行,使用的是的模塊化語法。我們使用需要用到的包一個(gè)任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯對(duì)應(yīng)的是同步任務(wù),從左到右,依次執(zhí)行任務(wù)。時(shí)間長對(duì)應(yīng)的是異步任務(wù),效率高,時(shí)間短。 gulp 是一個(gè)構(gòu)建工具,基于Node.js的平臺(tái)運(yùn)行,使用的是commonJs的模塊化語法。 我們使用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)行,使用的是的模塊化語法。我們使用需要用到的包一個(gè)任務(wù),對(duì)應(yīng)一個(gè)包,對(duì)應(yīng)一個(gè)處理邏輯對(duì)應(yīng)的是同步任務(wù),從左到右,依次執(zhí)行任務(wù)。時(shí)間長對(duì)應(yīng)的是異步任務(wù),效率高,時(shí)間短。 gulp 是一個(gè)構(gòu)建工具,基于Node.js的平臺(tái)運(yùn)行,使用的是commonJs的模塊化語法。 我們使用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中原理是一樣的,只不過可能有寫屬性在react-native中簡化了。有幾個(gè)注意...

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

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

0條評(píng)論

閱讀需要支付1元查看
<