使用Dockerfile創建鏡像


使用Dockerfile創建鏡像

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

1、基本結構

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

一般而言,Dockerfile主體內容分為四部分:基礎鏡像鏡像、維護者信息、鏡像操作指令和容器啟動時執行指令

2、指令說明

Dockerfile中指令的一般格式為:INSTRUCTION arguments,包括配置指令(配置鏡像信息)和操作指令(具體執行操作)

分類 指令 說明
配置指令 ARG 定義創建鏡像過程中使用的變量
FROM 指定所創建鏡像的基礎鏡像
LABEL 為生成的鏡像添加元數據標簽信息
EXPOSE 聲明鏡像內服務監聽的端口
ENV 指定環境變量
ENTRYPOINT 指定鏡像的默認入口命令
VOLUME 創建一個數據卷掛載點
USER 指定運行容器時的用戶名或UID
WORKDIR 配置工作目錄
ONBUILD 創建子鏡像時指定自動執行的操作指令
STOPSIGNAL 指定退出的信號值
HEALTHCHECK 配置所啟動容器如何進行健康檢查
SHELL 指定默認shell類型
操作指令 RUN 運行指定命令
CMD 啟動容器時指定默認執行的命令
ADD 添加內容到鏡像
COPY 復制內容到鏡像

2.1、配置指令介紹

ARG

定義創建鏡像過程中使用的變量

格式:

ARG <name>[=<default value>]

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

Docker內置了一些鏡像創建變量,用戶可以直接使用而無須聲明,包括(不區分大小寫)HTTP_PROXY、HTTPS_PROXY、FTP_PROXY、NO_PROXY。

FROM

指定所創建鏡像的基礎鏡像

格式:

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

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

為了保證鏡像精簡,可以選用體積較小的鏡像如Alpine或Debain作為基礎鏡像。

LABEL

LABEL指令可以為生成的鏡像添加元數據標簽信息。這些信息可以用來輔助過濾出特定鏡像。

格式:

LABEL <key>=<value> <key>=<value> <key>=<value>...

EXPOSE

聲明鏡像內服務監聽的端口。

格式:

EXPOSE <port> [<port>/<protocol>...]

eg:

EXPOSE 22 80 8443

注意:該指令只是起到聲明作用,並不會自動完成端口映射。

如果要映射端口出來,在啟動容器時可以使用-P參數(Docker主機會自動分配一個宿主機的臨時端口)或-p HOST_PORT:CONTAINER_PORT參數(具體指定所映射的本地端口)

ENV

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

格式:

ENV <key> <value> 或 ENV <key>=<value> 

eg:

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

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

注意:當一條ENV指令中同時為多個環境變量賦值且值也是從環境變量讀取時,會為變量都賦值后再更新。

如下面的指令,最終結果為:key1=value1 key2=value2

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

ENTRYPOINT

指定鏡像的默認入口命令,該入口命令會在啟動容器時作為根命令執行,所有傳入值作為該命令的參數。

支持以下兩種格式:

#exec調用執行
ENTRYPOINT ["executable","param1","param2"]、
#shell中執行
ENTRYPOINT command param1 param2

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

每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最后一個生效。

在運行時,可以被--entrypoint參數覆蓋掉,如:docker run --entrypoint(即覆蓋Dockerfile文件中ENTRYPOINT指令)

VOLUME

創建一個數據掛載點

格式:

VOLUME ["/data"]

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

USER

指定運行容器時的用戶名或UID,后續的RUN等指令也會使用指定的用戶身份。

格式:

USER daemon

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

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

如要臨時獲取管理員權限可以使用goru命令。

WORKDIR

為后續的RUN、CMD、ENTRYPOINT指令配置工作目錄。

格式:

WORKDIR /path/to/workdir

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

WORKDIR /a
WORKDIR b
WORKDIR c
#最終路徑為:/a/b/c

因此,為了避免出錯,推薦WORKDIR指令中只使用絕對路徑

ONBUILD

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

格式:

ONBUILD [INSTRUCYION]

例如,使用如下的Dockerfile創建父鏡像ParentImage,指定ONBUILD指令:

#Dockerfile for ParentImage
[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

使用docker build命令創建子鏡像ChildImage時(FROM ParentImage),會首先執行ParentImage中配置的ONBUILD指令:

#Dockerfile for ChildImage
FROM ParentImage

等價於在ChildImage的Dockerfile中添加了如下指令:

[...]
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src
...

由於ONBUILD指令是隱式執行的,推薦在使用它的鏡像標簽中進行標注,如:ruby:2.1-onbuild

ONBUILD指令在創建專門用於自動編譯、檢查等操作的基礎鏡像時,十分有用。

STOPSIGNAL

指定所創建鏡像啟動的容器接收退出的信號值

格式:

STOPSIGNAL signal

HEALTHCHECK

配置所啟動容器如何進行健康檢查(如何判斷健康與否)。

格式有兩種:

#根據所執行命令返回值是否為0來判斷
HEALTHCHECK [OPTIONS] CMD command
#禁止基礎鏡像中的健康檢查
HEALTHCHECK NONE

OPTION支持如下參數:

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

SHELL

指定其他命令使用shell時的默認shell類型

格式:

SHELL ["executable","parameters"]

默認值為["/bin/sh","-C"]

注意:對於windows系統,shell路徑中使用了“\”作為分隔符,建議在Dockerfile開頭添加”#escape=“來指定轉義符。

2.2、操作指令介紹

RUN

運行指定命令

格式:

RUN <command> 或 RUN ["executable","param1","param2"]

注意:后者指令會被解析為JSON數組,因此必須使用雙引號。前者默認將在shell終端中運行命令,即/bin/sh -c;后者則使用exec執行,不會啟動shell環境。

指定使用其他終端類型可以通過exec方式實現,如:

RUN ["/bin/bsah","-c",“echo hello world"]

每條RUN指令將在當前鏡像基礎上執行指定命令,並提交為新的鏡像層。當命令較長時,可用\來換行,如:

RUN apt-get update \
    && apt-get install -y python3 libbz2-dev \
    && rm -rf /var/cache/apt \
    && rm -rf /var/lib/apt/list/*

CMD

CMD指令用來指定啟動容器時默認執行的命令。

支持三種格式:

#推薦方式
CMD ["executable","param1","param2"]
#在默認的shell中執行,提供給需要交互的應用
CMD command param1 param2
#提供給ENTRYPOINT的默認參數
CMD ["param1","param2"]

每個Dockerfile只能有一條CMD命令。如果指定了多條,只有最后一條會被執行。

如果用戶啟動容器時手動指定了運行的命令(作為run命令的參數),則會覆蓋掉CMD指定的命令

ADD

添加內容到鏡像

格式:

ADD <src> <dest>
#該命令將復制指定的<src>路徑下內容到容器中的<dest>路徑下。

其中src可以是Dockerfile所在目錄的一個相對路徑(文件或目錄),也可以是一個URL,還可以是一個tar文件(自動解壓為目錄);dest可以是鏡像內絕對路徑,或者相對於WORKDIR的相對路徑。

COPY

復制內容到鏡像

格式:

COPY <src> <dest>

復制本地主機的src(Dockerfile所在目錄的相對路徑、文件或目錄)下內容到鏡像中的dest。目標路徑不存在時,會自動創建

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

3、Dockerfile示例

FROM node
MAINTAINER Taolei
RUN git clone -q https://github.com/docker-in-practice/todo.git
WORKDIR todo
RUN npm install > /dev/null
EXPOSE 8000
CMD ["npm","start"]

構建過程如下:

[root@aliyun docker]# pwd
/home/docker
#構建一個鏡像
[root@aliyun docker]# docker build .
Sending build context to Docker daemon  2.048kB
Step 1/7 : FROM node
latest: Pulling from library/node
0e29546d541c: Pull complete 
9b829c73b52b: Pull complete 
cb5b7ae36172: Pull complete 
6494e4811622: Pull complete 
6f9f74896dfa: Pull complete 
f2930ff7fb60: Pull complete 
c1d26179dd86: Pull complete 
1fa56dd41537: Pull complete 
321141c774e9: Pull complete 
Digest: sha256:36aca218a5eb57cb23bc790a030591382c7664c15a384e2ddc2075761ac7e701
Status: Downloaded newer image for node:latest
 ---> a283f62cb84b
Step 2/7 : MAINTAINER Taolei
 ---> Running in c367d3410334
Removing intermediate container c367d3410334
 ---> e7567eaaf35c
Step 3/7 : RUN git clone -q https://github.com/docker-in-practice/todo.git
 ---> Running in 9191275f23b1
Removing intermediate container 9191275f23b1
 ---> 5d80658a509b
Step 4/7 : WORKDIR todo
 ---> Running in f297028141cf
Removing intermediate container f297028141cf
 ---> a81464358a14
Step 5/7 : RUN npm install > /dev/null
 ---> Running in 19d637151604
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'minifyify@4.4.0',
npm WARN EBADENGINE   required: { node: '0.10.x' },
npm WARN EBADENGINE   current: { node: 'v17.3.0', npm: '8.3.0' }
npm WARN EBADENGINE }
npm WARN deprecated graceful-fs@2.0.3: please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js
npm WARN deprecated buffer-browserify@0.2.5: Package not maintained. Recent browserify uses https://github.com/feross/buffer
npm WARN deprecated mkdirp@0.3.5: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated mkdirp@0.3.5: Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)
npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated minimatch@0.3.0: Please update to minimatch 3.0.2 or higher to avoid a RegExp DoS issue
npm WARN deprecated react-tools@0.11.2: react-tools is deprecated. For more information, visit https://fb.me/react-tools-deprecated
npm notice 
npm notice New minor version of npm available! 8.3.0 -> 8.6.0
npm notice Changelog: <https://github.com/npm/cli/releases/tag/v8.6.0>
npm notice Run `npm install -g npm@8.6.0` to update!
npm notice 
Removing intermediate container 19d637151604
 ---> d1b737e8b68f
Step 6/7 : EXPOSE 8000
 ---> Running in 27157638d7d6
Removing intermediate container 27157638d7d6
 ---> 6fafd82e1672
Step 7/7 : CMD ["npm","start"]
 ---> Running in fe6d70c5ec05
Removing intermediate container fe6d70c5ec05
 ---> eafa085c10fa
Successfully built eafa085c10fa

步驟說明:

  1. docker會上傳docker build指定目錄下的文件和目錄
  2. 每個構建步驟從1開始按順序編號,並與命令一起輸出
  3. 每個命令會導致一個新鏡像被創建出來,其鏡像ID在此輸出
  4. 為節省空間,在繼續前每個中間容器會被移除
  5. 構建的調試信息在此輸出
  6. 此次構建的最終鏡像ID,可用於打標簽

打標簽

#打標簽前
[root@aliyun docker]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
<none>       <none>    eafa085c10fa   7 minutes ago   1.1GB
busybox      latest    beae173ccac6   3 months ago    1.24MB
node         latest    a283f62cb84b   3 months ago    993MB
#打標簽時
[root@aliyun docker]# docker tag eafa085c10fa todoapp
#打標簽后
[root@aliyun docker]# docker images
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
todoapp      latest    eafa085c10fa   8 minutes ago   1.1GB
busybox      latest    beae173ccac6   3 months ago    1.24MB
node         latest    a283f62cb84b   3 months ago    993MB

4、Dockerfile創建鏡像過程

編寫完Dockerfile之后,可使用docker build命令來創建鏡像。基本格式為:

docker build [OPTIONS] PATH | URL | -

創建過程:

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

如果上下文過大,會導致發送大量數據給服務端,延緩創建過程。故而除非是生成鏡像所必須的文件,不然不要放在上下文路徑下。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM