1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Docker之構(gòu)建鏡像

        共 7330字,需瀏覽 15分鐘

         ·

        2021-10-01 15:25

        本文就Docker下構(gòu)建鏡像的兩種方式作相關(guān)介紹

        abstract.png

        docker commit命令

        先創(chuàng)建一個(gè)Ubuntu 18.04的容器

        docker pull ubuntu:18.04

        docker run -it -d \
            --name ubuntu-1 \
            ubuntu:18.04

        在ubuntu-1容器中安裝tree命令

        # 進(jìn)入 ubuntu-1 容器
        docker exec -it ubuntu-1 /bin/bash
        # 更新軟件源
        apt update
        # 安裝 tree 命令
        apt -y install tree    
        # 退出 ubuntu-1 容器
        exit

        ubuntu-1容器中使用tree命令效果如下,說明tree命令安裝成功

        figure 1.jpg

        使用docker commit命令以u(píng)buntu-1容器來構(gòu)建鏡像,如下所示。其中,-m用于描述提交信息,-a用于描述作者。用戶倉庫的命名由用戶名、倉庫名兩部分組成,例如aaron1995/custom-ubuntu

        # 創(chuàng)建鏡像aaron1995/custom-ubuntu, 其中tag為1.0
        docker commit -m "add tree 2 in ubuntu" \
            -a "Aaron Zhu" \
            ubuntu-1 aaron1995/custom-ubuntu:1.0

        效果如下所示

        figure 2.jpg

        至此一個(gè)包含tree命令的鏡像就已經(jīng)構(gòu)建完畢了,后續(xù)我們就可以直接通過該鏡像來創(chuàng)建容器進(jìn)行使用。而不必每次都利用ubuntu:18.04鏡像創(chuàng)建容器,然后再在容器中安裝tree命令

        對(duì)于我們自行構(gòu)建的鏡像,使用過程也并無二異,命令如下所示

        docker run -it -d \
            --name ubuntu-2 \
            aaron1995/custom-ubuntu:1.0

        測(cè)試效果如下符合預(yù)期

        figure 3.jpg

        推送至Docker Hub

        我們還可以將我們的鏡像推送到Docker Hub,以方便共享給他人。需要注意的是,倉庫名稱(aaron1995/custom-ubuntu)中的用戶名(aaron1995)必須和Docker Hub賬號(hào)的用戶名保持一致,否則會(huì)推送失敗

        # 登陸 Docker Hub 賬號(hào),并輸入賬號(hào)、密碼
        docker login

        docker push aaron1995/custom-ubuntu:1.0

        效果如下所示

        figure 4.jpg

        在Docker Hub中查看,符合預(yù)期

        figure 5.jpg

        Dockerfile

        Demo

        事實(shí)上,我們更推薦使用Dockerfile來構(gòu)建鏡像。其通過一系列指令來描述鏡像的構(gòu)建過程,下面即是一個(gè)簡單的通過Dockerfile構(gòu)建鏡像的示例

        # 通過FROM指令 指定以 ubuntu:18.04 作為基礎(chǔ)鏡像
        FROM ubuntu:18.04

        # 通過MAINTAINER指令 設(shè)置作者信息
        MAINTAINER Aaron Zhu "[email protected]"

        # 通過RUN指令更新軟件源,其支持shell格式語法
        RUN apt update

        # 通過RUN指令安裝tree命令,其支持exec格式語法
        RUN ["apt""install""-y""tree"]

        # 通過RUN指令安裝nginx
        RUN apt install -y nginx

        # 通過RUN指令 修改nginx首頁頁面
        RUN echo "Hello World, I'm Aaron" > /var/www/html/index.nginx-debian.html

        # 通過CMD指令(exec格式語法) 設(shè)置Nginx前臺(tái)運(yùn)行
        CMD ["nginx""-g""daemon off;"]

        # 通過EXPOSE指定 聲明鏡像使用的端口
        EXPOSE 80

        效果如下所示

        figure 6.jpg

        然后通過docker build命令對(duì)該Dockerfile文件構(gòu)建鏡像,該命令需在Dockerfile文件所在目錄下執(zhí)行

        # 對(duì)當(dāng)前目錄下的Dockerfile文件構(gòu)建鏡像,-t選項(xiàng)設(shè)置鏡像名稱、tag
        docker build -t="aaron1995/dockerfile-demo:1.0" .

        效果如下符合預(yù)期

        figure 7.jpg

        現(xiàn)在我們來創(chuàng)建一個(gè)該鏡像的容器,驗(yàn)證下

        docker run -d \
            --name dockerfile-demo-1 \
            -p 4321:80 \
            aaron1995/dockerfile-demo:1.0

        測(cè)試結(jié)果如下符合預(yù)期

        figure 8.jpg

        指令詳解

        FROM

        該指令用于指定我們自定義鏡像的基礎(chǔ)鏡像,故第一條指令必須是FROM指令

        # 通過FROM指令 指定以 ubuntu:18.04 作為基礎(chǔ)鏡像
        FROM ubuntu:18.04

        MAINTAINER

        該指令用于描述作者信息。目前更推薦使用LABEL指令來定義作者信息等元數(shù)據(jù)

        # 通過MAINTAINER指令 設(shè)置作者信息
        MAINTAINER Aaron Zhu "[email protected]"

        RUN

        該指令用于描述鏡像構(gòu)建時(shí)需要執(zhí)行的命令,其支持shell、exec兩種形式的語法。示例如下

        # 通過RUN指令安裝tree命令,其支持shell格式語法
        RUN apt install -y tree

        # 通過RUN指令安裝tree命令,其支持exec格式語法
        RUN ["apt""install""-y""tree"]

        由于每次RUN指令都會(huì)建立一個(gè)新的鏡像層,導(dǎo)致最終鏡像體積膨脹。所以對(duì)于shell格式的多次RUN指令,推薦使用&&連接并利用反斜杠(\)進(jìn)行換行。示例如下所示

        # 優(yōu)化前: 多條RUN指令
        RUN apt update
        RUN apt install -y tree
        RUN apt install -y nginx

        # 優(yōu)化后: 使用&&進(jìn)行連接, 使用\換行
        RUN apt update \
         && apt install -y tree \
         && apt install -y nginx

        CMD

        該指令和RUN指令很類似,都是用于運(yùn)行命令的。只不過后者用于指定鏡像構(gòu)建時(shí)需要運(yùn)行的命令,而前者則指定容器被啟動(dòng)時(shí)需要運(yùn)行的命令。Docker推薦使用exec格式語法,例如上文中我們通過CMD指令設(shè)置設(shè)置Nginx前臺(tái)運(yùn)行

        需要注意的是:

        1. 如果Dockerfile文件中存在多條CMD指令,則只有最后一條CMD指令才會(huì)生效
        2. docker run中如果指定了命令,則其會(huì)覆蓋Dockerfile中的CMD指令,導(dǎo)致后者失效。這里我們嘗試創(chuàng)建一個(gè)新的容器,并在docker run中添加一個(gè)ls命令,如果可以覆蓋Dockerfile中的CMD指令,則該容器創(chuàng)建后一會(huì)兒就會(huì)結(jié)束退出。因?yàn)镹ginx是以后臺(tái)的方式運(yùn)行的
        # docker run中指定了要執(zhí)行的命令ls
        docker run -d \
            --name dockerfile-demo-2 \
            -p 5321:80 \
            aaron1995/dockerfile-demo:1.0 \
            ls

        測(cè)試結(jié)果如下,符合預(yù)期

        figure 9.jpg

        也正是因?yàn)榇耍芏鄷r(shí)候我們?nèi)萜鲃?chuàng)建過程中無需顯式指定需要執(zhí)行程序/命令,就是因?yàn)樵撶R像通過CMD指令設(shè)置了默認(rèn)行為。例如我們通過docker inspect查看下redis的鏡像信息,可以看到該鏡像通過CMD指令設(shè)置了容器默認(rèn)執(zhí)行redis-server命令

        figure 10.jpg

        故下述兩種創(chuàng)建redis容器的方式,本質(zhì)是一樣的

        # 方式1: 創(chuàng)建redis容器, 顯式執(zhí)行 redis-server 命令 
        docker run \
         -d -p 6379:6379 \
         --name Redis-Service \
         redis:6.2.3-alpine3.13 \
         redis-server

        # 方式2: 創(chuàng)建redis容器, 執(zhí)行默認(rèn)命令 redis-server
        docker run \
         -d -p 6379:6379 \
         --name Redis-Service \
         redis:6.2.3-alpine3.13

        EXPOSE

        該指令用于聲明鏡像所使用的端口,用于幫助鏡像使用者了解該鏡像所使用的端口信息。但并不會(huì)對(duì)外暴露相關(guān)端口,端口的映射需要在創(chuàng)建容器過程中通過-p、-P選項(xiàng)實(shí)現(xiàn)

        # 聲明端口及協(xié)議, 如果不指定協(xié)議默認(rèn)為TCP
        EXPOSE <port>/<protocol>

        # 聲明80端口, 使用TCP協(xié)議
        EXPOSE 80

        # 聲明80端口, 使用UDP協(xié)議
        EXPOSE 80/udp

        VOLUME

        定義匿名數(shù)據(jù)卷。即在鏡像中創(chuàng)建一個(gè)掛載目錄,默認(rèn)使用docker管理的匿名數(shù)據(jù)卷,也可通過docker run命令的-v選項(xiàng)掛載到宿主機(jī)上的指定目錄或數(shù)據(jù)卷。與docker run命令的-v選項(xiàng)不同,Dockerfile中不能指定宿主機(jī)目錄

        # 指定鏡像的掛載目錄, 如果目錄不存在會(huì)自動(dòng)創(chuàng)建
        VOLUME <路徑>

        # 指定鏡像的多個(gè)掛載目錄, 如果目錄不存在會(huì)自動(dòng)創(chuàng)建
        VOLUME ["<路徑1>""<路徑2>"]

        # 指定鏡像的掛載目錄, 如果目錄不存在會(huì)自動(dòng)創(chuàng)建
        VOLUME ["/home/aaron""/home/aaron/data"]

        dockerfile中定義了兩個(gè)掛載目錄,啟動(dòng)該容器后。效果如下所示,docker run命令中由于未使用-v選項(xiàng),故其默認(rèn)掛載匿名數(shù)據(jù)卷

        figure 11.jpg

        WORKDIR

        定義工作目錄。一方面,其會(huì)自動(dòng)創(chuàng)建相應(yīng)目錄;另一方面,其設(shè)置后續(xù)指令(RUN、CMD、COPY等)的工作目錄,類似于Linux的cd命令效果

        WORKDIR <路徑>

        WORKDIR指令可以在一個(gè)Dockerfile中使用多次。如果使用了相對(duì)路徑,它將相對(duì)于前一條WORKDIR指令的路徑。例如:

        WORKDIR /a
        WORKDIR b
        WORKDIR c
        RUN pwd

        最終pwd命令將會(huì)輸出/a/b/c,同時(shí)進(jìn)入該容器也會(huì)發(fā)現(xiàn)存在/a/b/c路徑

        COPY

        復(fù)制宿主機(jī)文件到容器內(nèi)。首先要求源文件位于Dockerfile所在的目錄下,如下所示

        figure 12.jpg

        然后通過COPY指令進(jìn)行復(fù)制

        # 復(fù)制game.txt文件到/home/down1/目錄中
        COPY game.txt /home/down1/
        # 復(fù)制源目錄picture下的所有文件到/home/down1/目錄下
        COPY picture/ /home/down1/
        # 將down2視作文件,復(fù)制mathBook.txt文件內(nèi)容覆蓋寫入其中
        COPY mathBook.txt /home/down2

        容器內(nèi)效果如下所示,符合預(yù)期。與此同時(shí)對(duì)于目標(biāo)目錄而言,如果不存在則會(huì)自動(dòng)進(jìn)行創(chuàng)建

        figure 13.jpg

        LABEL

        通過該指令添加元數(shù)據(jù)。如果值中包含空格,可使用引號(hào)或反斜杠(\)

        # 通過LABEL指令添加元數(shù)據(jù)
        LABEL <key>=<value>

        # 通過LABEL指令添加版本信息
        LABEL version=1.2.3.beta

        # 通過LABEL指令添加作者信息
        LABEL org.opencontainers.image.authors="Aaron Zhu"

        # 通過LABEL指令添加描述信息
        LABEL desc=This\ is\ a\ demo

        我們可通過docker inspect命令來查看容器的元數(shù)據(jù),效果如下所示

        figure 14.jpg

        ENV

        通過該指令定義環(huán)境變量。類似地,如果值中包含空格,可使用引號(hào)或反斜杠(\)

        # 通過ENV指令定義環(huán)境變量
        LABEL <key>=<value>

        # 示例
        ENV MY_NAME="Aaron Zhu"
        ENV MY_JOB=software\ engineer
        ENV MY_CAT=Tom

        事實(shí)上,創(chuàng)建容器時(shí)還可以通過 「docker run --env= 實(shí)現(xiàn)修改環(huán)境變量的值。示例如下所示

        docker run -itd --env MY_CAT="Bob Tony" \
            --name dockerfiledemo-02 \
            aaron1995/dockerfile-demo:1.0

        測(cè)試結(jié)果如下,符合預(yù)期

        figure 15.jpg

        Note

        • 在docker build命令的最后,我們還指定了一個(gè)目錄。如下圖所示,其中小圓點(diǎn).表示的是當(dāng)前路徑。因?yàn)镈ocker是以C/S架構(gòu)運(yùn)行的,在構(gòu)建過程中需要將指定目錄中的所有文件一起打包發(fā)送給Server端,即Docker引擎。故不要在Dockerfile所在的目錄中存放無用文件,避免導(dǎo)致構(gòu)建過程過長

        figure 16.jpg
        • Dockerfile文件無需添加文件類型后綴

        • Dockerfile文件支持注釋,以#開頭的行即會(huì)視作為注釋

        • Docker鏡像在構(gòu)建過程中利用了緩存機(jī)制。一旦有某個(gè)指令在緩存中未命中(即沒有該指令對(duì)應(yīng)的鏡像層),則后續(xù)的整個(gè)構(gòu)建過程都不會(huì)再使用緩存。故在編寫Dockerfile過程中,盡量將易于發(fā)生變化的指令置于Dockerfile文件的后方執(zhí)行,以便最大程度地利用緩存

        參考文獻(xiàn)

        1. 第一本Docker書·修訂版 James Turnbull著
        2. 深入淺出Docker [英]Nigel Poulton著
        瀏覽 93
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            我和饥渴岳性在公交车上电影 | 国产黑料av | 五月天色婷婷丁香 | 女女同女女女一区二区三区在线观看 | 女人男人交性爽视频 | 欧美成人三级在线视频 | 男女刺激性行为免费视频网站 | 佐山爱国产在线一区 | 男男罚跪夹玉势sm调教视频 | 女人裸体性做爰23 |