<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          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è)簡(jiǎn)單的通過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)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91麻豆影院 | 99视频在线观看国产 | 学生妹一级片 | 中文毛片| 欧美三级午夜理伦三级老人 |