Dockerfile中的保留字指令講解

語言: CN / TW / HK

之前簡單學過Docker,當時是為了快速部署一個專案,過的很快,對於Dockerfile檔案的編寫,有些顯的陌生。

所以就寫了這篇文章。希望能夠幫助到大家哦!!!

一、Dockerfile是什麼?

概念:

Dockerfile是用來構建Docker映象的構建檔案,由一系列命令和引數構成的指令碼

構建三步驟:

  1. 編寫Dockerfile檔案
  2. docker build
  3. docker run

Centos案例:

centos案例

FROM scratch  #真正的基礎映象,
ADD centos-7-x86_64-docker.tar.xz /

# label 說明的意思
LABEL \  
    org.label-schema.schema-version="1.0" \
    org.label-schema.name="CentOS Base Image" \
    org.label-schema.vendor="CentOS" \
    org.label-schema.license="GPLv2" \
    org.label-schema.build-date="20201113" \
    org.opencontainers.image.title="CentOS Base Image" \
    org.opencontainers.image.vendor="CentOS" \
    org.opencontainers.image.licenses="GPL-2.0-only" \
    org.opencontainers.image.created="2020-11-13 00:00:00+00:00"

CMD ["/bin/bash"] #最後一行執行的命令

在哪找到的勒,在hub.docker.com上找到滴:centos

我們不會,但是可以先去看看人家怎麼寫的,抄作業這事,我想大家都熟悉吧。俗稱CV大法😂。

二、Dockerfile構建過程分析

入門知識:

  1. 每條保留字指令(今天的重點)都必須為大寫字母並且後面要跟隨至少一個引數

    如:

    FROM scratch  #真正的基礎映象,
    ADD centos-7-x86_64-docker.tar.xz /
    
  2. 指令按照從上到下,順序執行

  3. #表示註釋。

    #這就是註釋
    
  4. 每條指令都會建立一個新的映象層,並對映象進行提交。

    就如下面這樣,可以套娃一樣。

image-20210902105639139

Dockerfile執行流程分析:

  1. docker從基礎映象執行一個容器
  2. 執行一條指令並對容器作出修改
  3. 執行類似docker commit的操作提交一個新的映象層。
  4. docker再基於剛提交的映象執行一個新容器
  5. 執行dockerfile中的下一條指令直到所有指令都執行完成

後文有案例,結合案例回過來看更容易理解。


小小番外

在現階段,我們將DockerfileDocker映象和Docker容器看待為軟體的三個不同階段。

Dockerfile面向開發--->Docker映象成為交付標準--->Docker容器則涉及部署與運維

  • Dockerfile中定義了程序所需要的一切東西,以前需要依賴的環境變數、依賴包、執行時環境等都被寫入到Dockerfile檔案中啦。比起之前你在Liunx伺服器中,下載那麼那麼多軟體,配置那麼那麼多,真的是簡單蠻多,起碼對於我這個菜雞來說用Docker部署真的簡單了蠻多的。

  • Docker映象是在用Dockerfile定義了一個檔案後,docker build 時產生的一個Docker映象,當執行時Docker映象時,才會真正開始提供服務。

  • Docker容器就是執行起來即可提供服務的。

三、Dockerfile保留字指令

Dockerfiel保留字指令大致有以下:

  1. FROM
  2. MAINTANINER
  3. RUN
  4. EXPOSE
  5. WORKDIR
  6. ENV
  7. ADD
  8. COPY
  9. VOLUME
  10. CMD
  11. ENTRYPOINT
  12. ONBUILD

3.1、FROM

基礎映象,即當前新映象是基於哪個映象建立的。

#基於openjdk:8 建立映象
FROM openjdk:8

3.2、MAINTAINER

映象維護者的姓名和郵箱地址

MAINTAINER 寧在春<[email protected]>

3.3、RUN

容器構建時需要執行的指令

RUN mkdir -p /conf/my.cn

3.4、EXPOSE

當前容器對外暴露的埠

#暴露出MyCat的所需埠
EXPOSE 8066 9066

3.5、WORKDIR

指定在建立容器後,終端預設登入的進來工作目錄

#容器資料卷,用於資料儲存和持久化工作
WORKDIR /usr/local/mycat

3.6、ENV

用來在構建映象過程中設定環境變數

#用來在構建映象過程中設定環境變數ENV MYCAT_HOME=/usr/local/mycat

這個環境變數可以在後續的任何RUN指令中使用,這就如同在命令前面指定了環境變數字首一樣;也可以在其它指令中直接使用這些環境變數。

如:

RUN $MYCAT_HOME/mycat

3.7、ADD 和 COPY

ADD

將宿主機目錄下的檔案拷貝進映象,並且ADD命令會自動處理URL和解壓tar壓縮包

ADD centos-6-docker.tar.xz / 

COPY

類似ADD,拷貝檔案和目錄到映象中。

將從構建上下文目錄中<源路徑>的檔案/目錄複製到新的一層的映象內的<目標路徑>位置

COPY src destCOPY ["src" "dest"]

3.8、VOLUME

容器資料卷,用於資料持久化和資料儲存。

#將mycat的配置檔案的地址暴露出對映地址,啟動時直接對映宿主機的資料夾VOLUME /usr/local/mycat

3.9、CMD 和 ENTRYPOINT

CMD

CMD的指令和RUN相似,也是兩種格式:

  • shell格式:CMD<命令>
  • exec 格式:CMD ["可執行檔案“,”引數1“,”引數2“.....]

Dockerfile中可以有多個CMD指令,但只有最後一個生效,CMD會被docker run 之後的引數替換。

ENTRYPOINT

指定一個容器啟動時要執行的命令。

ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動程式及引數。

區別

在這裡先簡單說明一下區別,你可以將CMD理解為覆蓋

CMD cat /conf/my.cnfCMD /bin/bash

這兩條指令都寫在Dockerfile檔案中,只會執行CMD /bin/bash ,而不會執行CMD cat /conf/my.cnf,因為CMD /bin/bash把上一條直接覆蓋掉了。

ENTRYPOINT則不同,你可以將ENTRYPOINT簡單理解為追加。

主要體現在docker run 上,如果使用dockerfile檔案中最後是CMD結尾,則在執行時不能夠額外追加命令,否則會覆蓋掉Dockerfile中的CMD命令。

Dockerfile檔案中最後一行為ENTRYPOINT結尾時,你可以在docker run 命令後追加一些命令.

3.10、ONBUILD

當構建一個被繼承的Dockerfile時執行命令,父映象在被子繼承後,父映象的onbuild被觸發。

四、實戰案例

4.1、製作一個自己的Centos映象

4.1.1、引入:

我們先從阿里雲上拉取一個centos看看,看看有哪些問題,然後我們再進行自定義。

docker pull centos # 拉取映象docker run -it centos #執行映象# ===== 測試====vim ceshi.txtifconfig pwd

image-20210902121641063

為什麼會這樣?因為docker倉庫中的Centos是精簡版,其只有核心,沒有其它的東西。

要求自定義的Centos能夠解決上述問題。

4.1.2、編寫Dockerfile檔案

為我們自定義的Centos 編寫Dockerfile檔案

FROM centosMAINTAINER 寧在春<[email protected]>ENV MYPATH /usr/localWORKDIR $MYPATHRUN yum -y install vimRUN yum -y install net-toolsEXPOSE 80 CMD echo $MYPATHCMD echo "success"CMD /bin/bash  #只會執行最後一個

image-20210902122905061

然後把這個複製進去即可。

mkdir -p /usr/local/docker/mycentos # 自己建立存放的位置vim Dockerfile

image-20210902123047491

4.1.3、構建centos映象

docker build -f /usr/local/docker/mycentos/Dockerfile  -t mycentos:1.1 .

解釋:

  • -f:後面跟隨的是Dockerfile 檔案

  • -t :後面跟隨的映象名和版本號。

  • 最後的小數點:就表明是當前目錄。

  • docker build -f Dockerfile檔案 -t 映象名:tag .
    
  • 當dockerfile檔案命名為dockerfile時並且在當前目錄下時可簡寫為:

  • docker build  -t 映象名:tag .docker build   -t mycentos:1.1 .
    

執行

image-20210902123755746

看到最後的這個就是代表成功了。

image-20210902123850158

docker images 檢視全部映象:

image-20210902123929428

4.1.4、執行Centos映象

docker run -it mycentos:1.3pwdifconfig

image-20210902124211273

之所以我們進去容器的目錄會從/切換到/usr/local是因為在dockerfile檔案中已經寫明。

ENV MYPATH /usr/localWORKDIR $MYPATH

4.1.5、檢視映象的變更歷史

docker history mycentos:1.1

image-20210902124619778

在這裡也可以看出來,映象它是由Dockerfile檔案中的指令,一層一層構建出來的。

4.2、ONBUILD示例

率先構建一個夫映象

編寫dockerfile檔案,命名為dockerfile2

FROM centosRUN yum -y install  curlONBUILD RUN echo "我被子映象繼承了,輸出此條語句"CMD ["crul", "-s","http://ip.cn"]
docker build -f /usr/local/docker/mycentos/Dockerfile2 -t my_father_centos .

image-20210902130405077

構建一個映象繼承夫映象

編寫dockerfile檔案,命名為dockerfile3

FROM my_father_centosRUN yum -y install  curlCMD ["crul", "-s","http://ip.cn"]
docker build -f /usr/local/docker/mycentos/Dockerfile3 -t my_son_centos .

image-20210902130626403

可以看到父映象中的語句被輸出了。

五、自言自語

紙上得來終覺淺,絕知此事要躬行。

大家好,我是博主寧在春主頁

一名喜歡文藝卻踏上程式設計這條道路的小青年。

希望:我們,待別日相見時,都已有所成

換個小貓表情,我們一起擊個掌吧。

image-20211102082517882