Docker學習⑤

使用Dockerfile創建鏡像

Dockerfile是一個文本格式的配置文件,用戶可以使用Dockerfile來快速創建自定義的鏡像。

 

基本結構

Dockerfile由一行行命令語句組成,並且支持以#開頭的註釋行。

一般而言,Dockerfile主體內容分爲四部分:

  1. 基礎鏡像信息;
  2. 維護者信息;
  3. 鏡像操作指令;
  4. 容器啓動時執行指令;

例:一個簡單的示例

【文檔解析】

首行可以通過註釋來指定解析器命令,後續通過註釋說明鏡像的相關信息。主體部分首先使用FROM指定指明所基於的鏡像名稱,接下來一般是使用LABEL指令說明維護者信息。後面則是鏡像操作指令,例如RUN指令對鏡像執行跟隨的命令。每運行一行RUN指令,鏡像添加新的一層,並提交。最後是CMD指令,來指定運行容器時的操作指令。

 

例:下面是Docker Hub上兩個熱門鏡像nginx和Go的Dockerfile例子

  • 第一個是在debian:jessie基礎鏡像基礎上安裝Nginx環境,從而創建一個新的nginx鏡像:
FROM debian:jessie

LABEL maintainer docker_user<[email protected]>

ENV NGINX_VERSION 1.10.1-1~jessie

Run apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 \
    && echo "deb http://nginx.org/packages/debian/ jessie nginx" >> /etc/apt/source.list \
        && apt-get update \
        && apt-get install --no-install-recommends --no-install-suggests -y \
        ca-certificates \
        nginx=$(NGINX_VERSION) \
        nginx-module-xslt \
        nginx-module-geoip \
        nginx-module-image-filter \
        nginx-module-perl \
        nginx-module-njs \
        gettext-base \
        && rm -rf /var/lib/apt/lists/*

#forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

EXPOSE 80 443

CMD ["nginx","-g","daemon off;"]
  • 第二個是基於buildpack-deps:jessie-scm基礎鏡像,安裝Golang相關環境,只做一個Go語言的運行環境鏡像:
FROM buildpack-deps:jessie-scm

#gcc for cgo
RUN apt-get update && apt-get install -y --no-install-recommends \
    g++ \
    gcc \
    libc6-dev \
    make \
    && rm -rf /var/lib/apt/lists/*

ENV GOLANG_VERSION 1.6.3
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 cdde5e08530c0579255d6153b08fdb3b8e47caabbe717bc7bcd7561275a87aeb

RUN curl -fsSL "$GOLANG_DOWNLOAD_URL" -o golang.tar.gz \
    && echo "$GOLANG_DOWNLOAD_SHA256 golang.tar.gz" | sha256sum -c - \
    && tar -C /usr/local -xzf golang.tar.gz \
    && rm golang.tar.gz

ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH

RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH

COPY go-wrapper /usr/local/bin/

指令說明

Dockerfile中指令的一般格式爲INSTRUCTION arguments,包括“配置指令”(配置鏡像信息)和“操作指令”(具體執行操作),參見表8-1。

  • 配置指令

1、ARG:定義創建鏡像過程中使用的變量

格式:ARG <name> [=<default value>]

在執行docker build時,可以通過-build-arg[=]來爲變量賦值。當鏡像編譯成功後,ARG指定的變量將不再存在(ENV指定的變量將在鏡像中保留)

 

2、FROM:指定所創建鏡像的基礎鏡像

格式:FROM <image> [AS <name>]FROM <image>:<tag> [AS <name>] FROM <image>@<digest> [AS <name>]

任何Dockerfile中第一條指令必須爲FROM指令。並且,如果在同一個Dockerfile中創建多個鏡像時,可以使用多個FROM指令(每個鏡像一次)。

爲了保證鏡像精簡,可以使用體積較小的鏡像如:

  • Alpine;
  • Debian;

 

3、LABEL:可以爲生成的鏡像添加元數據標籤信息。這些信息可以用來輔助過濾出特定鏡像。

格式:LABEL <key>=<value> <key>=<value> <key>=<value>...

例:

LABEL version="1.0.0-rc3"
LABEL author="yeasy@github" date="2020-01-01"
LABEL description="This text illistrates that label-values can span multiple lines."

 

4、ERPOSE:聲明鏡像內服務監聽的端口

格式:EXPOSE <port> [<port>/<protocol>...]

【注】

  1. 該指令只是起到聲明作用,並不會自動完成端口映射;
  2. 若要映射端口出來,在啓動容器時可以使用-P參數(Docker主機會自動分配一個宿主機的臨時端口)或-p HOST_PORT:CONTAINER_PORT參數(具體指定所映射的本地端口)

 

5、ENV

指定環境變量,在鏡像生成過程中會被後續RUN指令使用,在鏡像啓動的容器中也會存在

格式:ENV <key> <value> 或 ENV <key>=<value>...

例:

ENV APP_VERSION=1.0.0
ENV APP_HOME=/usr/local/app
ENV PATH $PATH:/usr/local/bin

指令指定的環境變量在運行時可以被覆蓋掉,如docker run --env <key>=<value> built_image

【注】

注意當一條ENV指令中同時爲多個環境變量賦值並且值也是從環境變量讀取時,會爲變量都賦值後再更新。如下面指令,最終結果爲key1=value1 AND key2=value2:

ENV key1=value2
ENV key1=value1 key2=${key1}

 

6、ENTRYPOINT:指定鏡像的默認入口命令,該入口命令會在啓動容器時作爲根命令執行,所有傳入值作爲該命令的參數。

格式:

  1. ENTRYPOINT ["executable","param1","param2"]: exec調用執行;
  2. ENTRYPOINT command param1 param2: shell中執行;

此時,CMD指令指定值將作爲根命令的參數。

【注】每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最後一個起效。在運行時候,可被--entrypoint覆蓋。

 

7、VOLUME:創建一個數據掛載點

格式:VOLUME ["/data"]

運行容器時可以從本地主機或其他容器掛載數據卷,一般用來存放數據庫和需要保持的數據等。

 

8、USER:指定運行容器時的用戶名或UID,後續的RUN等指令也會使用指定的用戶身份

格式:USER daemon

當服務不需要管理員權限時,可以通過該命令指定運行用戶,並且可以在Dockerfile中創建所需要的用戶。

例:

RUN groupadd -r postgres && useradd --no-log-init -r -g postgres postgres

【注】要臨時獲取管理員權限可以使用gosu命令。

 

9、WORKDIR:爲後續的RUN、CMD、ENTRYPOINT指令配置工作目錄

格式:WORKDIR /path/to/workdir

可以使用多個WORKDIR指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。

例:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

則最終路徑爲/a/b/c

【注】爲了避免出錯,推薦WORKDIR指令中只使用絕對路徑。

 

10、ONBUILD:指定當基於所生成鏡像創建子鏡像時,自動執行的操作指令

格式:ONBUILD [INSTRUCTION]

 

11、STOPSIGNAL:指定所創建鏡像啓動的容器接收退出的信號值

格式:STOPSIGNAL signal

 

12、HEALTHCHECK:配置所啓動容器如何進行健康檢查(如何判斷健康與否)

格式:HEALTHCHECK [OPTIONS] CMD command:根據所執行指令返回值是否爲0來判斷;

           HEALTHCHECKK NONE:禁止基礎鏡像中的健康檢查;

[OPTIONS]參數解析:

  1. --interval=DURATION (default:30s):過多久檢查一次;
  2. --timeout=DURATION (dafalut:30s):每次檢查等待結果的超時;
  3. -retries=N (default:3):如果失敗了,重試幾次才最終確定失敗;

 

13、SHELL:指定其他命令使用shell時的默認shell類型

格式:SHELL ["executable","parameters"]

默認值爲["/bin/sh","-c"]

 

  • 操作指令

1、RUN:運行指定命令

格式:RUN <command>RUN ["executable","param1","param2"]

【注】

  1. 後者指令會被解析爲JSON數組,因此必須使用雙引號;
  2. 前者默認將在shell終端中運行命令,即/bin/sh -c;
  3. 後者使用exec執行,不會啓動shell環境;

指定使用其他終端類型課可以通過第二種方式實現:RUN ["/bin/bash","-c","echo hello"]

 

2、CMD:用來指定啓動容器時默認執行的命令

支持三種格式:

  1. CMD ["executable","param1","param2"]:相當於執行executable param1 param2【推薦】;
  2. CMD command param1 param2:在默認的Shell中執行,提供給需要交互的應用;
  3. CMD ["param1","param2"]:提供給ENTRYPOINT的默認參數;

【注】

  1. 每個Dockerfile只能有一條CMD命令。如果指定了多條命令,只有最後一條會被執行;
  2. 如果用戶確定容器時手動指定了運行的命令(作爲run的參數),則會覆蓋CMD指定的命令;

 

3、ADD:添加內容到鏡像

格式:ADD <src> <dest>

格式解析:這條命令將複製指定的<src>路徑下內容到容器中的<dest>路徑下;同時,src可以是相對路徑、URL、tar文件(自動解壓爲目錄),dest可以是鏡像內絕對路徑或者相對於工作目錄(WORKDIR)的相對路徑(支持正則格式)。

 

4、COPY:複製內容到鏡像

格式:COPY <src> <dest>

複製本地主機的<src>(爲Dockerfile所在目錄的相對路徑、文件或目錄)下內容到鏡像中的<dest>;目標路徑不存在時,會自動創建;路徑同樣支持正則格式。

【注】COPY和ADD指令功能相似,當使用本地目錄爲源目錄時,推薦使用COPY。

 

  • 創建鏡像

編寫完成Dockerfile之後,可以通過docker [image]  build命令來創建鏡像。

格式:docker build [OPTIONS] PATH | URL | -

該命令讀取指定路徑下的Dockerfile,並將該路徑下所有數據作爲上下文發送給Docker服務端。Docker服務端在校驗Dockerfile格式通過後,逐條執行其中定義的指令,碰到ADD、COPY和RUN指令會生成一層新的鏡像。最終如果創建成功,會返回最終鏡像的ID。

如果上下文過大,會導致發送大量數據給服務端,延緩創建過程。因此除非是生成鏡像所必須的文件,不然不要放到上下文路徑下。如果使用非上下文路徑下的Dockerfile,可以通過-f選項來指定其路徑。

例:上下文路徑爲/tmp/docker_builder/,並且希望生成鏡像標籤爲builder/first_image:1.0.0,可以使用如下

docker build -t builder/first_image:1.0.0 /tmp/docker_builder/

 

1、命令選項

 

2、選擇父鏡像

大部分情況下,生成新的鏡像都需要通過FROM指令來指定父鏡像。父鏡像是生成鏡像的基礎,會直接影響到所生成鏡像的大小和功能。

用戶可選擇兩種鏡像作爲父鏡像:

  1. 基礎鏡像;
  2. 普通的鏡像(由第三方創建,基於基礎鏡像);

基礎鏡像比較特殊,其Dockerfile中往往不存在FROM指令,或者基於scratch鏡像,這意味着其在整個鏡像處於根的位置。

例:下面定義了一個簡單的基礎鏡像,將用戶提前編譯好的二進制可執行文件binary複製到鏡像中,運行容器時執行binary指令

FROM scratch
ADD binary /
CMD ["/binary"]

 

發佈了92 篇原創文章 · 獲贊 6 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章