文章目錄
- 一、Dockerfile介紹
- 二、Dockerfile鏡像制作和流程使用
- 三、Dockerfile文件的制作鏡像的分層結構
- 四、Dockerfile文件格式
- 五、Dockerfile相關指令
- 5.1 FROML:指定基礎鏡像
- 5.2 LABEL:指定鏡像元數據
- 5.3 RUN:執行shell指令
- 5.4 ENV:設置環境變量
- 5.5 COPY:復制文本
- 5.6 ADD:復制和解包文件
- 5.7 CMD啟動容器命令
- 5.8 ENTRYPOINT:入口點
- 5.9 ARG:構建參數
- 5.10 VOLUME:匿名卷
- 5.11 EXPOSE:暴露端口
- 5.12 WORKDIR:指定工作目錄
- 5.13 ONBUILD:子鏡像引用父鏡像的指令
- 5.14 USER:指定當前用戶
- 5.15 HEALTHCHECK:健康檢查
- 5.16 STOPSIGNAL:退出容器的信號
- 5.17 SHELL:指定shell
- 5.18 .dokcerignore文件
- 5.19 Dockerfile構建過程和指令總結
- 六、構建鏡像的docker build命令
一、Dockerfile介紹
DockerFile是一種被Docker程序解釋執行的腳本,由一條條的命令組成的,每條命令對應linux下面的一條命令,Docker程序將這些DockerFile指令再翻譯成真正的linux命令,其有自己的書寫方式和支持的命令,Docker程序讀取DockerFile并根據指令生成Docker鏡像,相比手動制作鏡像的方式,DockerFile更能直觀的展示鏡像是怎么產生的,有了DockerFile,當后期有額外的需求時,只要在之前的DockerFile添加或者修改響應的命令即可重新生成新的Docker鏡像,避免了重復手動制作鏡像的麻煩,類似于shell腳本一樣,可以方便高效的制作鏡像
二、Dockerfile鏡像制作和流程使用
三、Dockerfile文件的制作鏡像的分層結構
例:按照業務類型或系統類型等方式劃分創建目錄環境,方便后期鏡像比較多的時候進行分類
[root@node4 ~]# mkdir -p /data/dockerfile/{web/{nginx,tomcat,jdk},system/{centos,ubuntu,apline,debian}}
[root@node4 ~]# tree /data/dockerfile/
/data/dockerfile/
├── system
│ ├── apline
│ ├── centos
│ ├── debian
│ └── ubuntu
└── web├── jdk├── nginx└── tomcat9 directories, 0 files
四、Dockerfile文件格式
dockerfile官方說明:https://docs.docker.com/engine/reference/builder/
幫助:man 5 dockerfile
DockerFile文件說明
-
每一行以Dockerfile的指令開頭,指令不區分大小寫,但是慣例使用大寫
-
使用#開始作為注釋
-
每一行只支持一條指令,每條指令可以攜帶多個參數
-
指令按文件的順序從至下進行執行
-
每個指令的執行會生成一個新的鏡像層,為了減少分層和鏡像大小,盡可能將多條指令合并成一條指令
-
制鏡像一般可能需要反復多次,每次執行dockfile都按順序執行,從頭開始,已經執行過的指令已經緩存,不需要再執行,如果后續有一行新的指令沒執行過,其往后的指令將會重新執行,所以為加速鏡像制作,將最常變化的內容放下dockerfile的文件的后面
五、Dockerfile相關指令
dockerfile文件中的常見指令
ADD
COPY
ENV
EXPOSE
FROM
LABEL
STOPSIGNAL
USER
VOLUME
WORKDIR
5.1 FROML:指定基礎鏡像
FROM就是指定基礎鏡像,此指令通常必需放在Dockerfile文件第一個非注釋行。后續的指令都是運行于此基準鏡像所提供的運行環境
例:
FROM [--platform=<platform>]<image>[AS <name>]
FROM [--platform=<platform>]<image>[:<tag>][AS <name>]
FROM [--platform=<platform>]<image>[@<digest>][AS <name>]#說明:
--platform指定鏡像的平臺,比如:linux/amd64,linux/arm64,or windows/amd64 tag和digest是可選項,如果不指定,默認為latestFROM scratch #所有鏡像的起源鏡像,相當于object類
FROM ubuntu
FROM ubuntu:bionic
FROM debian:buster-slim
5.2 LABEL:指定鏡像元數據
可以指定鏡像元數據,如:鏡像作者等
LABEL <key>=<value> <key>=<value> <key>=<value> ...
例:
LABEL version="1.0"
LABEL description="This text illustrates"
一個鏡像可以有多個label,還可以寫在一行中,即多標簽寫法,可以減少鏡像的的大小
例:
#一行格式
LABEL multi.label1="value1" multi.label2="value2" other="value3'#多行格式
LABEL multi.label1="value1"\multi.label2="value2"\other="value3"
MAINTAINER:指令維護者信息,此指令已過時,用LABEL代替
5.3 RUN:執行shell指令
RUN指令用來在構建鏡像階段需要執行FROM指定鏡像所支持的Shll命令。
注:RUN可以寫多個,每一個RUN指令都會建立一個鏡像層,所以盡可能合并成一條指令,比如將多個shell命令通過&&連接一起成為在一條指令
每個RUN都是獨立運行的和前一個RUN無關
#shell格式:相當于/bin/sh-c <命令> 此種形式支持環境變量
RUN <命令>#exec格式:此種形式不支持環境變量,注意:是雙引號,不能是單引號
RUN["可執行文件","參數1","參數2"]#exec格式可以指定其它shell
RUN ["/bin/bash","-c","echo hello wang"]
5.4 ENV:設置環境變量
ENV可以定義環境變量和值,會被后指鈴如:ENV,ADD,COPY,RUN等通過KEY或KEY或KEY或{KEY}進行引用,并在容器運行時保持
#變量賦值格式1
ENV <key> <value> #此格式只能對一個key賦值,<key>之后的所有內容均會被視作其<value>的組成部分#變量賦值格式2
ENV <key1>=<value1> <key2>=<value2> \ #此格式可以支持多個key賦值,定義多個變量建議使用,減少鏡像層<key3>=<value3> ...#如果<value>中包含空格,可以以反斜線 \ 進行轉義,也可通過對<value>加引號進行標識;另外,反斜線也可用于續行#只使用一次變量
RUN <key>=<value> <command>#引用變量
RUN $key ......
#變量支持高級賦值格式
${key:-word}
$[kye:+word}
如果運行容器時如果需要修改變量,可以執行下面通過基于exec機制實現
注意:下面方式只影響容器運行時環境,而不影響構建鏡像的過程,即只能覆蓋docker run時的環境變量,而不會影響docker build時環境變量的值
docker run -e|--env <key>=<value>#說明
-e,--env list #Set environment variables--env-file filename #Read in a file of environment variables
5.5 COPY:復制文本
復制本地宿主機的內容到容器中
COPY [--chown=<user>:<group>] <src>...<dest>
COPY [--chowm-<user>:<group>] ["<src>",..."<dest>"]#路徑中有空白字符時,建議使用此格式
說明:
-
·以是多個,可以使用通配符,通配符規則滿足Go的filepath.Match規則filepath.Match參考鏈接https://go1ang.org/pkg/path/filepath/#Match
-
必須是build上下文中的路徑(為Dockerfile所在目錄的相對路徑),不能是其父目錄中的文件
-
如果是目錄,則其內部文件或子目錄會被遞歸復制,但目錄自身不會被復制
-
如果指定了多個,或在其中使用了通配符,則必須是一個目錄,且必須以/結尾
-
可以是絕對路徑或者是WORKDIR指定的相對路徑
-
使用COPY指令,源文件的各種元數據都會保留。比如讀、寫、執行權限、文件變更時間等
-
如果事先不存在,它將會被自動創建,這包括其父目錄路徑即遞歸創建目錄
5.6 ADD:復制和解包文件
該命令可認為是增強版的COPY,不僅支持COPY,還支持自動解縮。可以將復制指定的到容器中
ADD [--chown=<user>:<group>] <src>...<dest>
ADD [--chowm-<user>:<group>] ["<src>",..."<dest>"]#路徑中有空白字符時,建議使用此格式
說明:
-
可以是Dockerfile所在目錄的一個相對路徑;也可是一個URL;還可是一個tar文件(自動解壓)
-
可以是絕對路徑或者是WORKDIR指定的相對路徑
-
如果是目錄,只復制目錄中的內容,而非目錄本身
-
如果是一個URL,下載后的文件權限自動設置為600
-
如果為URL且不以/結尾,則指定的文件將被下載并直接被創建,如果以/結尾,則文件名URL指定的文件將被直接下載并保存為/
-
如果是一個本地文件系統上的打包文件如:g2,bz2,xz,它將被解包,其行為類以于"tar -x"命令,但是通過URL獲取到的tar文件將不會自動展開(注:zip后綴的包不會被解壓)
-
如果有多個,或其間接或直接使用了通配符,則必須是一個以/結尾的目錄路徑,如果不以/結尾,則其被視作一個普通文件。
5.7 CMD啟動容器命令
一個容器中需要持續運行的進程一般只有一個,CMD用來指定啟動容器時默認執行的一個命令,且其運行結束后,容器也會停止,所以一般CMD指定的命令為持續運行且為前臺命令。
-
每個Dockerfile只能有一條CMD命令。如果指定了多條,只有最后一條被執行
-
如果用戶啟動容器時用docker run xxx指定運行的命令,則會覆蓋CMD指定的命令
#使用exec執行,推薦方式,第一個參數必須是命令的全路徑,此種形式不支持環境變量
CMD ["executable","paraml","param2"]#在/bin/sh中執行,提供給需要交互的應用;此種形式支持環境變量
CMD command paraml param2#提供給ENTRYPOINT命令的默認參數
CMD ["param1","param2"]
例:
CMD ["nginx","-g","daemon off;"]
5.8 ENTRYPOINT:入口點
功能類似于CMD,配置容器啟動后執行的命令及參數
#使用exec執行
ENTRYPOINT ["executable","param1","param2"]#shell中執行
ENTRYPOINT command param1 param2
-
ENTRYPOINT不能被docker run提供的參數覆蓋,而是追加,即如果docker run命令有參數,那么參數全部都會作為ENTRYPOINT的參數
-
如果docker run后面沒有額外參數,但是dockerfile中的CMD里有(即上面CMD的第三種用法),即Dockerfile中有CMD也有ENTRYPOINT,那么CMD的全部內容會作為ENTRYPOINTE的參數
-
如果docker run后面有額外參數,同時Dockerfile中即有CMD也有ENTRYPOINT,那么docker run后面的參數覆蓋掉CMD參數內容最終作為ENTRYPOINT的參數
-
可以通過docker run --entrypoint string參數在運行時替換,注意string不要加空格
-
使用CMD要在運行時重新寫命令本身,然后在后面才能追加運行參數,ENTRYPOINT則可以運行時無需重寫命令就可以直接接受新參數
-
每個Dockerfile中只能有一個ENTRYPOINT,當指定多個時,只有最后一個生效
5.9 ARG:構建參數
ARG指令在build階段指定變量,和ENV不同的是,容器運行時不會存在這些環境變量
ARG <name>[=<default value>]
如果和ENV同名,ENV覆蓋ARG變量
可以用docker build-build-arg<參數名>=<值> 來覆蓋
說明:ARG和FROM
#FROM指令支持由第一個FROM之前的任何ARG指令聲明的變量
#例
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app#在FROM之前聲明的ARG在構建階段之外,所以它不能在FROM之后的遷何指令中使用。要使用在第一個FROM之前聲明的ARG的默認值,請在構建階段內使用沒有值的ARG指令
#例:
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
5.10 VOLUME:匿名卷
在容器中創建一個可以從本地主機或其他容器掛載的掛載點,一般用來存放數據庫和需要保持的數據等,一般會將宿主機中的目錄掛載至VOLUME指令指定的容器目錄。即使容器后期被刪除,此宿主機的目錄仍會保留,從而實現容器數據的持久保存。
VOLUME <容器內路徑>
VOLUME ["<容器內路徑1>","<容器內路徑2>"...]
注意
-
Dockerfile中的VOLUME實現的是匿名數據卷無法指定宿主機路徑和容器目錄的掛載關系
-
通過docker rm -fv <容器ID>刪除容器的同時,也會刪除VOLUME指定的卷
5.11 EXPOSE:暴露端口
指定服務端的容器需要對外暴露監聽的端口號,以實現容器與外部通信。
EXPOSE僅僅是聲明容器打算使用什么端口而已,并不會真正暴露端口,即不會自動在宿主機進行端口映射。
因此,在啟動容器時需要通過-P或-p,Docker主機才會真正分配一個端口轉發到指定暴露的端口才可使用
注意:即使Dockerfile沒有EXPOSE端口指令,也可以通過docker run -p臨時暴露容器內程序真正監聽的端口,所以EXPOSE相當于指定默認的暴露端口,可通過docker run -P進行真正暴露
EXPOSE <port>[/ <protocol>][<port>[/ <protocol> ..]#說明
<protocol>用于指定傳輸層協議,可為tCp或udp二者之一,默認為TCP協議
5.12 WORKDIR:指定工作目錄
為后續的RUN、CMD、ENTRYPOINT指令配置工作目錄,當容器運行后,進入容器內WORKDIR指定的默認目錄
WORKDIR指定工作目錄(或稱當前目錄),以后各層的當前目錄就被改為指定的目錄,如該目錄不存在,WORKDIR會自行創建
可以使用多個ORKDIR指鈴,后續命令如果參數是相對路徑,則會基于之前命令指定的路徑
例:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd結果為/a/b/c
5.13 ONBUILD:子鏡像引用父鏡像的指令
可以用來配置當構建當前鏡像的子鏡像時,會自動觸發執行的指令,但在當前鏡像構建時,并不會執行,即延遲到子鏡像構建時才執行
ONBUILD [INSTRUCTION]
如果基于image-A創建新的鏡像image-B時,新的Dockerfile中使用FROM image-A指定基礎鏡像時,會自動執行ONBUILD指令內容,等階于在后面添動加了兩條指令。
說明:
-
盡管任何指令都可注冊成為觸發器指令,但ONBUILD不能自我嵌套,且不會觸發FROM和MAINTAINER指令
-
使用ONBUILD指令的鏡像,推薦在標簽中注明,例收如ruby:1.9-onbui1d
5.14 USER:指定當前用戶
指定運行容器時的用戶名或UID,后續的RUN也會使用指定用戶
當服務不需要管理員權限時,可以通過該命令指定運行用戶
這個用戶必須是事先建立好的,否則無法切換
如果沒有指定USER,默認是root身份執行
USER <user>[:<group>]
USER <UID>[:<GID>]
5.15 HEALTHCHECK:健康檢查
檢查容器的健康性
HEALTHCHECK [選項] CMD <命令> #設置檢查容器健康狀況的命令
HEALTHCHECK NONE #如果基礎鏡像有健康檢查指令,使用這行可以屏薇掉其健康檢查指令HEALTHCHECK支持下列選項:
--interval=<間隔> #兩次健康檢查的間隔,默認為30秒
--timeout=<時長> #健康檢查命令運行超時時間,如果超過這個時間,本次健康檢查就被視為失敗,默認30秒
--retries=<次數> #當連續失敗指定次數后,則將容器狀態視為unhealthy,默認3次
--start-period=<FDURATION> #default:0s#檢查結果返回值:
0 #success the container is healthy and ready for use
1 #unhealth the container is not working correctly
2 #reserved do not use this exit code
例:
FROM nginx
RUN apt-get update & apt-get install -y curl &8 rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s
CMD curl -fs http://localhost/ || exit 1
5.16 STOPSIGNAL:退出容器的信號
該STOPSIGNAL指令設置將被發送到容器退出的系統調用信號。該信號可以是與內核syscall表中的位置匹配的有效無符號數字(例如9),也可以是SIGNAME格式的信號名稱(例如SIGKILL)
5.17 SHELL:指定shell
SHELL指令允許覆蓋用于命令的shell形式的默認SHELL,必須在Dockerfile中以JSON形式編寫SHELL指令。
5.18 .dokcerignore文件
官方文檔:https://docs.docker.com/engine/reference/builder/#dockerignore-file,與.gitignore文件類似,生成構建上下文時Docker客戶端應忽略的文件和文件夾指定模式
dockerignore使用Go的文件路徑規則filepath.Match
參考鏈接:https://golang.org/pkg/path/filepath/#Match
完整的語法
# #以#開頭的行為注釋
* #匹配任何非分隔符字符序列
? #匹配任何單個非分隔符
N #表示\
** #匹配任意數量的目錄(包括零)例如,**/*.go將排除在所有目錄中以.go結尾的所有文件,包括構建上下文的根。
! #表示取反,可用于排除例外情況
5.19 Dockerfile構建過程和指令總結
Dockerfile構建過程
-
從基礎鏡像運行一個容器
-
執行一條指令,對容器做出修改
-
執行類似docker commit的操作,提交一個新的中間鏡像層(可以利用中間層鏡像創建容器進行調試和排錯)
-
再基于剛提交的鏡像運行一個新容器
-
執行Dockerfile中的下一條指令,直至所有指令執行完畢
六、構建鏡像的docker build命令
docker build命令使用Dockerfile文件創建鏡像
[root@node4 ~]# docker build --helpUsage: docker build [OPTIONS] PATH | URL | -說明:
PATH | URL | - #可以使是本地路徑,也可以是URL路徑。若設置為-,則從標準輸入獲取Dockerfi1e的內容
-f,--file string #Dockerfile.文件名,默認為PATH/Dockerfile
--force-rm #總是刪除中間層容器,創建鏡像失敗時,刪除臨時容器
--no-cache #不使用之前構建中創建的緩存
-q --quiet=false #不顯示Dockerfile的RUN運行的輸出結果
--rm=true #創建鏡像成功時,刪除臨時容器
-t --tag list #設置注冊名稱、鏡像名稱、標簽。格式為<注冊名稱>/<鏡像名稱>:<標簽>(標簽默認為latest)Build an image from a DockerfileOptions:--add-host list Add a custom host-to-IP mapping (host:ip)--build-arg list Set build-time variables--cache-from strings Images to consider as cache sources--cgroup-parent string Optional parent cgroup for the container--compress Compress the build context using gzip--cpu-period int Limit the CPU CFS (Completely Fair Scheduler) period--cpu-quota int Limit the CPU CFS (Completely Fair Scheduler) quota-c, --cpu-shares int CPU shares (relative weight)--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)--disable-content-trust Skip image verification (default true)-f, --file string Name of the Dockerfile (Default is 'PATH/Dockerfile')--force-rm Always remove intermediate containers--iidfile string Write the image ID to the file--isolation string Container isolation technology--label list Set metadata for an image-m, --memory bytes Memory limit--memory-swap bytes Swap limit equal to memory plus swap: '-1' to enable unlimited swap--network string Set the networking mode for the RUN instructions during build (default "default")--no-cache Do not use cache when building the image--pull Always attempt to pull a newer version of the image-q, --quiet Suppress the build output and print image ID on success--rm Remove intermediate containers after a successful build (default true)--security-opt strings Security options--shm-size bytes Size of /dev/shm-t, --tag list Name and optionally a tag in the 'name:tag' format--target string Set the target build stage to build.--ulimit ulimit Ulimit options (default [])
查看鏡像的構建歷史:docker history 鏡像ID
不利用緩存重新構建鏡像:docker build --no-cache -t …