1. 前言
Dockerfile 是用來(lái)構(gòu)建自定義 Docker 鏡像的文本文檔暴拄。我們通過(guò)docker build
命令用于從Dockerfile 文件構(gòu)建鏡像榕茧。 如果你要構(gòu)建自定義鏡像,Dockerfile 是你必須學(xué)會(huì)的技能之一。
2. Dockerfile 的基本結(jié)構(gòu)
Dockerfile 一般分為:基礎(chǔ)鏡像、鏡像元信息跟匆、鏡像操作指令和容器啟動(dòng)時(shí)執(zhí)行指令,#
為 Dockerfile 中的注釋通砍。
3. Dockerfile 文件說(shuō)明
Docker 從上到下的順序運(yùn)行Dockerfile 的指令玛臂,每一個(gè)指令都以 step
為步驟。而且文件的命名也必須為 Dockerfile
封孙。
4. Dockerfile 常用的指令迹冤。
接下來(lái)對(duì)常用的 Dockerfile 指令進(jìn)行總結(jié)。
4.1 FROM 指令
FROM
是指定基礎(chǔ)鏡像虎忌,必須為第一個(gè)命令泡徙,格式:
FROM <image>:<tag>
其中 tag
或 digest
是可選的,如果不使用這兩個(gè)值時(shí)膜蠢,會(huì)使用 latest
版本的基礎(chǔ)鏡像堪藐。
示例: FROM mysql:5.6
4.2 MAINTAINER 指令
MAINTAINER
用來(lái)聲明維護(hù)者信息,該命令已經(jīng)過(guò)期,推薦使用 LABEL
挑围,格式:
MAINTAINER <name>
4.3 LABEL 指令
LABEL:用于為鏡像添加元數(shù)據(jù),多用于聲明構(gòu)建信息礁竞,作者、機(jī)構(gòu)杉辙、組織等模捂。格式:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
示例: LABEL version="1.0" description="felord.cn" by="Felordcn"
使用LABEL
指定元數(shù)據(jù)時(shí),一條LABEL指定可以指定一或多條元數(shù)據(jù)奏瞬,指定多條元數(shù)據(jù)時(shí)不同元數(shù)據(jù)之間通過(guò)空格分隔。推薦將所有的元數(shù)據(jù)通過(guò)一條LABEL指令指定泉孩,以免生成過(guò)多的中間鏡像硼端。
4.4 ENV 指令
ENV
用來(lái)設(shè)置環(huán)境變量,格式:
ENV <key> <value>
ENV <key>=<value>
示例: ENV version 1.0.0
或者 ENV version=1.0.0
可以通過(guò) ${key}
在其它指令中來(lái)引用變量寓搬,如 ${version}
珍昨。我們也可以通過(guò) docker run
中的 -e <ENV>
來(lái)動(dòng)態(tài)賦值
4.5 ARG 指令
ARG
用于指定傳遞給構(gòu)建運(yùn)行時(shí)的變量,格式:
ARG <name>[=<default value>]
通過(guò) docker run
中的 --build-arg <key>=<value>
來(lái)動(dòng)態(tài)賦值,不指定將使用其默認(rèn)值镣典。
4.6 WORKDIR 指令
WORKDIR
用來(lái)指定工作目錄兔毙,類似于我們通常使用的cd
命令,格式:
WORKDIR <PATH>
通過(guò) WORKDIR
設(shè)置工作目錄兄春,Dockerfile 中的其它指令 RUN
澎剥、CMD
、ENTRYPOINT
赶舆、ADD
哑姚、COPY
等命令都會(huì)在該目錄下執(zhí)行。在使用 docker run
運(yùn)行容器時(shí)芜茵,可以通過(guò) -w
參數(shù)覆蓋構(gòu)建時(shí)所設(shè)置的工作目錄叙量。
4.7 ADD 指令
ADD
用于將本地文件添加到鏡像中,tar
類型文件會(huì)自動(dòng)解壓(網(wǎng)絡(luò)壓縮資源不會(huì)被解壓)九串,可以訪問(wèn)網(wǎng)絡(luò)資源绞佩,類似 wget
,格式:
ADD <src>... <dest>
# 用于支持包含空格的路徑
ADD ["<src>",... "<dest>"]
示例:
ADD home* /path/ # 支持通配符 * 添加所有以"home"開頭的文件 到/path/ 下
4.8 COPY 指令
COPY
的功能類似于 ADD
猪钮,但是不會(huì)自動(dòng)解壓文件品山,也不能訪問(wèn)網(wǎng)絡(luò)資源
4.9 RUN 指令
RUN
用來(lái)執(zhí)行構(gòu)建鏡像時(shí)執(zhí)行的命令,有以下兩種命令執(zhí)行方式:
-
shell
執(zhí)行格式:
RUN <command>
示例:RUN apk update
-
exec
執(zhí)行格式:
RUN ["executable", "param1", "param2"]
示例: RUN ["/dev/file", "p1", "p2"]
需要注意的是: RUN
指令創(chuàng)建的中間鏡像會(huì)被緩存躬贡,并會(huì)在下次構(gòu)建中使用谆奥。如果不想使用緩存鏡像,可在構(gòu)建時(shí)指定 --no-cache
參數(shù)拂玻,示例:docker build --no-cache
4.10 CMD 指令
CMD
構(gòu)建容器后執(zhí)行的命令酸些,也就是在容器啟動(dòng)時(shí)才執(zhí)行的命令。格式:
# 執(zhí)行可執(zhí)行文件檐蚜,優(yōu)先執(zhí)行
CMD ["executable","param1","param2"]
# 設(shè)置了 ENTRYPOINT魄懂,則直接調(diào)用ENTRYPOINT添加參數(shù) 參見 CMD 講解
CMD ["param1","param2"]
# 執(zhí)行shell命令
CMD command param1 param2
示例: CMD ["/usr/bin/bash","--help"]
CMD
不同于 RUN
,CMD
用于指定在容器啟動(dòng)時(shí)所要執(zhí)行的命令闯第,而RUN用于指定鏡像構(gòu)建時(shí)所要執(zhí)行的命令市栗。
4.11 ENTRYPOINT 指令
ENTRYPOINT
用來(lái)配置容器,使其可執(zhí)行化咳短。配合 CMD
可省去 application
填帽,只使用參數(shù)。格式:
#可執(zhí)行文件, 優(yōu)先
ENTRYPOINT ["executable", "param1", "param2"]
# shell內(nèi)部命令
ENTRYPOINT command param1 param2
示例:
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
ENTRYPOINT
與 CMD
非常類似咙好,不同的是通過(guò) docker run
執(zhí)行的命令不會(huì)覆蓋 ENTRYPOINT
篡腌,而 docker run
命令中指定的任何參數(shù)都會(huì)被當(dāng)做參數(shù)再次傳遞給 ENTRYPOINT
指令。Dockerfile 中只有最后一個(gè) ENTRYPOINT
命令起作用勾效,也就是說(shuō)如果你指定多個(gè)ENTRYPOINT
,只執(zhí)行最后的 ENTRYPOINT
指令嘹悼。
4.12 EXPOSE 指令
EXPOSE
指定與外界交互的端口叛甫,格式:
EXPOSE [<port>...]
示例: EXPOSE 8080 443
、EXPOSE 80
杨伙、EXPOSE 11431/tcp 12551/udp
EXPOSE
并不會(huì)直接讓容器的端口映射主機(jī)其监。宿主機(jī)訪問(wèn)容器端口時(shí),需要在 docker run
運(yùn)行容器時(shí)通過(guò) -p
來(lái)發(fā)布這些端口限匣,或通過(guò) -P
參數(shù)來(lái)發(fā)布EXPOSE
導(dǎo)出的所有端口
4.13 VOLUME 指令
VOLUME
用于指定持久化目錄, 格式:
VOLUME ["<src>",...]
示例:VOLUME ["/data"]
抖苦,VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
一個(gè)卷可以存在于一個(gè)或多個(gè)容器的指定目錄,該目錄可以繞過(guò)聯(lián)合文件系統(tǒng)膛腐,并具有以下功能:
- 卷可以容器間共享和重用
- 容器并不需要要和其它容器共享卷
- 修改卷后會(huì)立即生效
- 對(duì)卷的修改不會(huì)對(duì)鏡像產(chǎn)生影響
- 卷會(huì)一直存在睛约,直到?jīng)]有任何容器在使用它
和 EXPOSE
指令類似, VOLUME
并不會(huì)掛載的宿主機(jī)哲身,需要通過(guò) docker run
運(yùn)行容器時(shí)通過(guò) -v
來(lái)映射到宿主機(jī)的目錄中辩涝。參見另一個(gè)命令 docker volume create
4.14 USER 指令
USER
指定運(yùn)行容器時(shí)的用戶名或 UID
,后續(xù)的 RUN
也會(huì)使用指定用戶勘天。使用 USER
指定用戶時(shí)怔揩,可以使用用戶名、UID
或GID
脯丝,或是兩者的組合商膊。當(dāng)服務(wù)不需要管理員權(quán)限時(shí),可以通過(guò)該命令指定運(yùn)行用戶宠进。并且可以在之前創(chuàng)建所需要的用戶,格式:
USER user
USER user:group
USER uid:group
USER uid
USER user:gid
USER uid:gid
使用 USER
指定用戶后晕拆,Dockerfile 中其后的命令 RUN
、CMD
材蹬、ENTRYPOINT
都將使用該用戶实幕。你可以通過(guò) docker run
運(yùn)行容器時(shí),可以通過(guò) -u
參數(shù)來(lái)覆蓋指定用戶堤器。
4.15 ONBUILD 指令
ONBUILD
作用是其當(dāng)所構(gòu)建的鏡像被用做其它鏡像的基礎(chǔ)鏡像昆庇,該鏡像中的 ONBUILD
中的命令就會(huì)觸發(fā),格式:
ONBUILD [INSTRUCTION]
示例:
ONBUILD ADD . /application/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
5. 總結(jié)
今天對(duì)構(gòu)建 Docker 鏡像腳本 Dockerfile 基本命令進(jìn)行的詳細(xì)的總結(jié)闸溃,并加以舉例說(shuō)明整吆,相信能解決你在構(gòu)建鏡像中的一些困惑。敬請(qǐng)多多關(guān)注微信公眾號(hào):Felordcn 辉川,后續(xù)將會(huì)有更多干貨奉上表蝙。
附: Spring Boot Dockerfile
# 使用 aws 的java jdk 8
FROM amazoncorretto:8
# 作者等相關(guān)的元信息
LABEL AUTHOR=Felordcn OG=felord.cn
# 掛載卷
VOLUME ["/tmp","/logs"]
# 時(shí)區(qū)
ENV TZ=Asia/Shanghai
# 啟用配置文件 默認(rèn)為 application.yml
ENV ACTIVE=defualt
# 設(shè)置鏡像時(shí)區(qū)
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 修改為打包后的jar文件名稱
ADD /target/flyway-spring-boot-1.0.0.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=${ACTIVE}","-jar","app.jar"]