天天看點

docker系列—Dockerfile詳解

介紹

鏡像的制作方式有兩種

  1. 基于容器制作,但這樣的鏡像不利于維護,不适合線上使用。
  2. 另一種就是就是要介紹的Dockerfile,Dockerfile就是建構鏡像的源代碼,當時和我們編寫程式的源代碼不同,Dockerfile是一些指令的組合。

簡要概括Dockerfile的作用:可以讓使用者個性化定制Docker鏡像。因為不同的工作環境需求不同,網絡上已存在的鏡像不能完全滿足自己的需求,此時就需要利用Dockerfile來建構自己可以滿足自己需求的鏡像。

格式

  1. Dockerfile整體就兩類語句組成:
    • 注釋資訊,以 # 辨別的行為注釋行
    • 指令參數,一行一個指令。
  2. Dockerfile檔案名首字母必須大寫。
  3. Dockerfile指令不區分大小寫,但是為友善和參數做區分,通常指令使用大寫字母。
  4. Dockerfile中指令按順序從上至下依次執行。
  5. Dockerfile中第一個非注釋行必須是FROM指令,用來指定制作目前鏡像依據的是哪個基礎鏡像。
  6. Dockerfile中需要調用的檔案必須跟Dockerfile檔案在同一目錄下,或者在其子目錄下,父目錄或者其它路徑無效。

指令集

FROM

  • FROM

    指令必須為Dockerfile檔案開篇的第一個非注釋行,用于指定建構鏡像所使用的基礎鏡像,後續的指令運作都要依靠此基礎鏡像所提供的的環境(簡單說就是假如Dockerfile中所引用的基礎鏡像裡面沒有mkdir指令,那後續的指令是沒法使用mkdir參數的。)
  • 實際使用中,如果沒有指定倉庫,docker build會先從本機查找是否有此基礎鏡像,如果沒有會預設去Docker Hub Registry上拉取,再找不到就會報錯。

文法

FROM [--platform=<platform>] <image> [AS <name>]
or
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
or
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
           

scratch 是最基礎的一個空白鏡像。 下面是官方的centos的Dockerfile

docker系列—Dockerfile詳解

RUN

  • RUN

    指令将在目前鏡像的頂部中執行所有指令,并送出結果,生成的鏡像将用于下一條指令。
  • RUN

    下一次建構期間,指令緩存不會自動失效。類似指令的緩存 RUN apt-get dist-upgrade -y将在下一個建構中重用。

    RUN

    指令的緩存可以通過使用–no-cache 标志來使無效,例如docker build --no-cache。

文法

shell形式,指令在shell中運作,預設情況下/bin/sh -c在Linux或cmd /S /CWindows 上運作

參數是一個JSON格式的數組,其中

"executable"

為要運作的指令,後面的"paramN"為傳遞給指令的選項或參數。此格式指定的指令不會以

"/bin/sh-c"

來發起,也就是直接由核心建立,是以不具備shell特性,類似于

RUN [ "echo", "$HOME" ]

,是無法識别 $ 的;如果想要依賴shell特性,可以替換指令為這樣的格式

[ "/bin/sh", "-c", "echo $HOME" ]

CMD

  • 指定啟動容器的預設要運作的程式,也就是PID為1的程序指令,且其運作結束後容器也會終止。如果不指定,預設是bash。
  • CMD

    指令指定的預設程式會被docker run指令行指定的參數所覆寫。
  • Dockerfile中可以存在多個

    CMD

    指令,但僅最後一個生效。因為一個docker容器隻能運作一個PID為1的程序。
  • 類似于

    RUN

    指令,也可以運作任意指令或程式,但是兩者的運作時間點不同,RUN指令運作在docker build的過程中,而CMD指令運作在基于新鏡像啟動容器(docker run)時。

文法

前兩種文法格式同RUN指令。第一種用法對于CMD指令基本沒有意義,因為它運作的程式PID不為1。

CMD command param1 param2

CMD ["executable","param1","param2"](exec形式,這是首選形式)
           

第三種則需要結合ENTRYPOINT指令使用,CMD指令後面的指令作為ENTRYPOINT指令的預設參 數。如果docker run指令行結尾有參數指定,那CMD後面的參數不生效。

CMD ["param1","param2"](作為ENTRYPOINT的預設參數)
           

LABEL

  • 同docker run -l
  • 使用者可以為鏡像指定各種中繼資料(鍵值對的格式)。

文法

可以在一行或者使用 \ 來拼接,來減少鏡像的層,最終減小鏡像的大小。

LABEL multi.label1="value1" multi.label2="value2" other="value3"
or
LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"
           

MAINTAINER

已棄用,LABEL要靈活的多。

EXPOSE

  • 通知Docker容器在運作時監聽指定的網絡端口。可以指定端口是偵聽TCP還是UDP,如果未指定協定,則預設值為TCP。
  • docker run --expose

文法

示例

EXPOSE 80/tcp
EXPOSE 80/udp
           

ENV

  • ENV

    指令将環境變量設定為

    <key><value>

    。此值将在建構階段中所有後續指令的環境中使用。調用格式為

    $variable_name或者${variable_name}

  • docker run -e

文法

ENV <key> <value>
ENV <key>=<value> ...
           
  1. 第一種形式,ENV

    <key> <value>

    會将一個變量設定為一個值。第一個空格之後的整個字元串将被視為-包括空格字元。該值将為其他環境變量解釋,是以如果不對引号字元進行轉義,則将其删除。
  2. 第二種形式ENV

    <key>=<value> ...

    允許一次設定多個變量。請注意,第二種形式在文法中使用等号(=),而第一種形式則不使用等号(=)。像指令行解析一樣,引号和反斜杠可用于在值中包含空格。
  3. 定義多個變量時,建議使用第二種方式,因為Dockerfile中每一行都是一個鏡像層,建構起來比較吃資源。

ADD

  • ADD

    指令跟

    COPY

    類似,不過它還支援使用tar檔案和URL路徑。
  • 當拷貝的源檔案是tar檔案時,會自動展開為一個目錄并拷貝進新的鏡像中;然而通過URL擷取到的tar檔案不會自動展開。複制或解壓縮目錄時,其行為與相同tar -x。

文法

ADD [--chown=<user>:<group>] <src>... <dest>
or
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"] (此格式對于包含空格的路徑是必需的)
           

規則

  1. 該路徑必須是内部語境的建構; 不能這樣做ADD …/something /something,因為第一步 docker build是将上下文目錄(和子目錄)發送到docker守護程式。
  2. 如果是URL,并且不以斜杠結尾,則從URL下載下傳檔案并将其複制到。
  3. 如果是URL并以斜杠結尾,則從URL推斷檔案名,然後将檔案下載下傳到 /。例如,ADD http://example.com/foobar /将建立檔案/foobar。該URL必須具有非平凡的路徑,以便在這種情況下可以發現适當的檔案名(http://example.com 将不起作用)。
  4. 如果是目錄,則将複制目錄的整個内容,包括檔案系統中繼資料。

COPY

  • 複制主控端上的檔案到目标鏡像中

文法

COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"] (此格式對于包含空格的路徑是必需的)
           

規則

同 ADD

ENTRYPOINT

  • 類似

    CMD

    指令的功能,用于為容器指定預設運作程式。
  • Dockerfile中可以存在多個

    ENTRYPOINT

    指令,但僅最後一個生效
  • CMD

    差別在于,由

    ENTRYPOINT

    啟動的程式不會被

    docker run

    指令行指定的參數所覆寫,而且這些指令行參數會被當做參數傳遞給

    ENTRYPOINT

    指令指定的程式。不過,

    docker run

    的-

    -entrypoint

    選項的參數可覆寫

    ENTRYPOINT

    指定的預設程式

文法

ENTRYPOINT ["executable", "param1", "param2"] (執行表格,首選)
ENTRYPOINT command param1 param2 
           

VOLUME

  • 等同于

    docker run -v

  • 用于在鏡像中建立一個挂載點目錄。在dockerfile中隻支援docker管理的卷,也就是說隻能指定容器内的路徑,不能指定主控端的路徑。主控端可以通過

    docker inspect container

    檢視。

文法

注意事項

  • 基于Windows的容器上的卷:使用基于Windows的容器時,容器内的卷的目的地必須是以下之一:
    1. 不存在或空目錄
    2. 除以下以外的驅動器 C:
  • 從Dockerfile内更改卷:如果在聲明了卷後有任何建構步驟更改了卷内的資料,則這些更改将被丢棄。
  • JSON格式:清單被解析為JSON數組。必須用雙引号(")而不是單引号(’)包覆單詞。
  • 主機目錄是在容器運作時聲明的:主機目錄(挂載點)從本質上說是依賴于主機的。這是為了保留圖像的可移植性,因為不能保證給定的主機目錄在所有主機上都可用。是以,無法從Dockerfile内挂載主機目錄。該VOLUME指令不支援指定host-dir 參數。建立或運作容器時,必須指定安裝點。

WORKDIR

  • docker run -w

  • 指定工作目錄,可以指多個,每個

    WORKDIR

    隻影響他下面的指令,直到遇見下一個

    WORKDIR

    為止。
  • WORKDIR

    也可以調用由ENV指令定義的變量。

文法

WORKDIR /path/to/workdir
           
  1. 該WORKDIR指令可以在Dockerfile中多次使用。如果提供了相對路徑,則它将相對于上一條WORKDIR指令的路徑

例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
則最終路徑為/a/b/c
           

ARG

  • AR

    G指令同

    EVN

    類似,也是指定一個變量,但不同的是,

    ENV

    指令配合

    -e

    參數可以在

    docker run

    過程中傳參,而使用

    ARG

    指令配合

    --build-arg

    參數可以在

    docker build

    過程中傳參,這友善了我們為不同場景建構不同鏡像。

文法

ONBUILD

  • 用于在Dockerfile中定義一個觸發器。
  • ONBUILD

    後面指定的指令在

    docker build

    時是不會執行,建構完的鏡像在被另一個Dockerfile檔案中FROM指令所引用的時才會觸發執行。

文法

STOPSIGNAL

  • 指定發送使容器退出的系統調用信号。

    docker stop

    之是以能停止容器,就是發送了15的信号給容器内PID為1的程序。

文法

STOPSIGNAL signal