dockerfile介紹與使用小結(jié)
文檔:https://docs.docker.com/engine/reference/builder/
dockerfile介紹
dockerfile是什么
Dockerfile是一個創(chuàng)建鏡像所有命令的文本文件, 包含了一條條指令和說明, 每條指令構(gòu)建一層, 通過 docker build命令,根據(jù)Dockerfile的內(nèi)容構(gòu)建鏡像,因此每一條指令的內(nèi)容, 就是描述該層如何構(gòu)建.有了 Dockefile, 就可以制定自己的docker鏡像規(guī)則,只需要在Dockerfile上添加或者修改指令, 就可生成 docker 鏡像.
dockerfile解決了什么問題
Dockerfile 包含了鏡像制作的完整操作流程,其他開發(fā)者可以通過 Dockerfile 了解并復(fù)現(xiàn)制作過程 Dockerfile 中的每一條指令都會創(chuàng)建新的鏡像層,這些鏡像可以被 Docker Daemon 緩存。再次制作鏡 像時,Docker 會盡量復(fù)用緩存的鏡像層(using cache),而不是重新逐層構(gòu)建,這樣可以節(jié)省時間和 磁盤空間 Dockerfile 的操作流程可以通過docker image history [鏡像名稱]查詢,方便開發(fā)者查看變更記錄
docker build 構(gòu)建流程
docker build命令會讀取Dockerfile的內(nèi)容,并將Dockerfile的內(nèi)容發(fā)送給 Docker 引擎,最終 Docker 引擎會解析Dockerfile中的每一條指令,構(gòu)建出需要的鏡像。
第一步,docker build會將 context 中的文件打包傳給 Docker daemon。如果 context 中 有.dockerignore文件,則會從上傳列表中刪除滿足.dockerignore規(guī)則的文件。注意:如果上下文中有相當(dāng)多的文件,可以明顯感受到整個文件發(fā)送過程。
這里有個例外,如果.dockerignore文件中有.dockerignore或者Dockerfile,docker build命令在排除文件時會忽略掉這兩個文件。如果指定了鏡像的 tag,還會對 repository 和 tag 進(jìn)行驗(yàn)證。
第二步,docker build命令向 Docker server 發(fā)送 HTTP 請求,請求 Docker server 構(gòu)建鏡像,請求中 包含了需要的 context 信息。
第三步,Docker server 接收到構(gòu)建請求之后,會執(zhí)行以下流程來構(gòu)建鏡像:
1. 創(chuàng)建一個臨時目錄,并將 context 中的文件解壓到該目錄下。
2. 讀取并解析 Dockerfile,遍歷其中的指令,根據(jù)命令類型分發(fā)到不同的模塊去執(zhí)行。
3. Docker 構(gòu)建引擎為每一條指令創(chuàng)建一個臨時容器,在臨時容器中執(zhí)行指令,然后 commit 容器, 生成一個新的鏡像層。
4. 最后,將所有指令構(gòu)建出的鏡像層合并,形成 build 的最后結(jié)果。最后一次 commit 生成的鏡像 ID 就是最終的鏡像 ID。
為了提高構(gòu)建效率,docker build默認(rèn)會緩存已有的鏡像層。如果構(gòu)建鏡像時發(fā)現(xiàn)某個鏡像層已經(jīng)被緩 存,就會直接使用該緩存鏡像,而不用重新構(gòu)建。如果不希望使用緩存的鏡像,可以在執(zhí)行docker build命令時,指定--no-cache=true參數(shù)。
Docker 匹配緩存鏡像的規(guī)則為:遍歷緩存中的基礎(chǔ)鏡像及其子鏡像,檢查這些鏡像的構(gòu)建指令是否和當(dāng) 前指令完全一致,如果不一樣,則說明緩存不匹配。對于ADD、COPY指令,還會根據(jù)文件的校驗(yàn)和 (checksum)來判斷添加到鏡像中的文件是否相同,如果不相同,則說明緩存不匹配。 這里要注意,緩存匹配檢查不會檢查容器中的文件。比如,當(dāng)使用RUN apt-get -y update命令更新了容 器中的文件時,緩存策略并不會檢查這些文件,來判斷緩存是否匹配。 最后,可以通過docker history命令來查看鏡像的構(gòu)建歷史。
關(guān)鍵字
FROM 設(shè)置鏡像使用的基礎(chǔ)鏡像
MAINTAINER 設(shè)置鏡像的作者
RUN 編譯鏡像時運(yùn)行的腳步
CMD 設(shè)置容器的啟動命令
LABEL 設(shè)置鏡像標(biāo)簽
EXPOSE 設(shè)置鏡像暴露的端口
ENV 設(shè)置容器的環(huán)境變量
ADD 編譯鏡像時復(fù)制上下文中文件到鏡像中
COPY 編譯鏡像時復(fù)制上下文中文件到鏡像中
ENTRYPOINT 設(shè)置容器的入口程序
VOLUME 設(shè)置容器的掛載卷
USER 設(shè)置運(yùn)行 RUN CMD ENTRYPOINT的用戶名
WORKDIR 設(shè)置 RUN CMD ENTRYPOINT COPY ADD 指令的工作目錄
ARG 設(shè)置編譯鏡像時加入的參數(shù)
ONBUILD 設(shè)置鏡像的ONBUILD 指令
STOPSIGNAL 設(shè)置容器的退出信號量
dockerfile 實(shí)踐
基本語法實(shí)踐
mkdir example cd example
vim Dockerfile
FROM golang ENV env1=env1value ENV env2=env2value MAINTAINER zloser # 僅指定鏡像元數(shù)據(jù)內(nèi)容 LABEL hello 1.0.0 RUN git clone https://gitee.com/nickdemo/helloworld.git WORKDIR helloworld RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app . EXPOSE 80 CMD ["./app","--param1=p1","--param2=p2"]
docker build -t hello:1.0.0 -f Dockerfile . docker run -p 80:80 -d --name hello hello:1.0.0
構(gòu)建成功:

docker build上下文
1. 素材準(zhǔn)備
# 創(chuàng)建一個目錄,案例需要 mkdir example2 cd example2 # 下載nginx源碼包,作為案例素材 curl https://nginx.org/download/nginx-1.21.6.tar.gz > ./nginx-1.21.6.tar.gz # 下載app代碼 git clone https://gitee.com/nickdemo/helloworld
# ./nginx* # helloworld
2. 沒有什么作用的上下文
FROM golang ENV env1=env1value ENV env2=env2value MAINTAINER zloser # 僅指定鏡像元數(shù)據(jù)內(nèi)容 LABEL hello 1.0.0 RUN git clone https://gitee.com/nickdemo/helloworld.git WORKDIR helloworld RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app . EXPOSE 80 CMD ["./app","--param1=p1","--param2=p2"]
# 調(diào)整為不同的上下文,查看不同的效果 docker build -t hello:1.0.0 -f Dockerfile .
3. 上下文的真正作用
FROM golang:1.18 ENV env1=env1value ENV env2=env2value MAINTAINER zloser LABEL hello 1.0.0 COPY ./helloworld /go/src/helloworld WORKDIR /go/src/helloworld RUN go env -w GOPROXY=https://proxy.golang.com.cn,https://goproxy.cn,direct RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app . EXPOSE 80 CMD ["./app","--param1=p1","--param2=p2"]
docker build -t hello:1.0.0 -f Dockerfile .
操作:
1. 嘗試在.dockerignore 文件中忽略不同的內(nèi)容,觀察發(fā)送到守護(hù)進(jìn)程的數(shù)據(jù)
2. 嘗試 采用不同的上下文路徑來構(gòu)建鏡像
3. 嘗試 copy上下文以外的內(nèi)容來構(gòu)建鏡像
多階段構(gòu)建
Docker 17.05版本以后,新增了Dockerfile多階段構(gòu)建。所謂多階段構(gòu)建,實(shí)際上是允許一個Dockerfile 中出現(xiàn)多個 FROM 指令。這樣做有什么意義呢? 多個 FROM 指令的意義 多個 FROM 指令并不是為了生成多根的層關(guān)系,最后生成的鏡像,仍以最后一條 FROM 為準(zhǔn),之前的 FROM 會被拋棄,那么之前的FROM 又有什么意義呢? 每一條 FROM 指令都是一個構(gòu)建階段,多條 FROM 就是多階段構(gòu)建,雖然最后生成的鏡像只能是最后 一個階段的結(jié)果,但是,能夠?qū)⑶爸秒A段中的文件拷貝到后邊的階段中,這就是多階段構(gòu)建的最大意義。 最大的使用場景是將編譯環(huán)境和運(yùn)行環(huán)境分離,比如,之前我們需要構(gòu)建一個Go語言程序,那么就需要用到go命令等編譯環(huán)境
ADD 與 COPY
1. ADD 與 COPY 不能拷貝上下文以外的文件
2. COPY 命令語法格式
COPY <src> <dest> //將上下文中源文件,拷貝到目標(biāo)文件 COPY prefix* /destDir/ //將所有prefix 開頭的文件拷貝到 destDir 目錄下 COPY prefix?.log /destDir/ //支持單個占位符,例如 : prefix1.log、prefix2.log 等
3. 對于目錄而言,COPY 和 ADD 命令具有相同的特點(diǎn):只復(fù)制目錄中的內(nèi)容而不包含目錄自身
COPY srcDir /destDir/ //只會將源文件夾srcDir下的文件拷貝到 destDir 目錄下
4. COPY 區(qū)別于ADD在于Dockerfile中使用multi-stage
5. ADD 命令語法
ADD <src> <dest>
ADD 命令除了不能用在 multistage 的場景下,ADD 命令可以完成 COPY 命令的所有功能,并且還可以 完成兩類的功能:
a.解壓壓縮文件并把它們添加到鏡像中,對于宿主機(jī)本地壓縮文件,ADD命令會自動解壓并添加到鏡像
b.從 url 拷貝文件到鏡像中,需要注意:url 所在文件如果是壓縮包,ADD 命令不會自動解壓縮
CMD 與 ENTRYPOINT
CMD
CMD 指令有三種格式
# shell 格式 CMD <command> # exec格式,推薦格式 CMD ["executable","param1","param2"] # 為ENTRYPOINT 指令提供參數(shù) CMD ["param1","param2"]
1. CMD 指令提供容器運(yùn)行時的默認(rèn)值,這些默認(rèn)值可以是一條指令,也可以是一些參數(shù)。
2. 一個dockerfile中可以有多條CMD指令,但只有最后一條CMD指令有效。
3. CMD參數(shù)格式是在CMD指令與ENTRYPOINT指令配合時使用,CMD指令中的參數(shù)會添加到 ENTRYPOINT指令中。
4. 使用shell 和exec 格式時,命令在容器中的運(yùn)行方式與RUN 指令相同。不同在于,RUN指令在構(gòu)建鏡像時執(zhí)行命令,并生成新的鏡像。
5. CMD指令在構(gòu)建鏡像時并不執(zhí)行任何命令,而是在容器啟動時默認(rèn)將CMD指令作為第一條執(zhí)行的命令。如果在命令行界面運(yùn)行docker run 命令時指定命令參數(shù),則會覆蓋CMD指令中的命令。
ENTRYPOINT
ENTRYPOINT指令有兩種格式
# shell 格式 ENTRYPOINT <command> # exec 格式,推薦格式 ENTRYPOINT ["executable","param1","param2"]
1. ENTRYPOINT指令和CMD指令類似,都可以讓容器每次啟動時執(zhí)行相同的命令,但它們之間又有不 同。一個Dockerfile中可以有多條ENTRYPOINT指令,但只有最后一條ENTRYPOINT指令有效。
2. 當(dāng)使用shell格式時,ENTRYPOINT指令會忽略任何CMD指令和docker run 命令的參數(shù),并且會運(yùn) 行在bin/sh -c中。
3. 推薦使用exec格式,使用此格式,docker run 傳入的命令參數(shù)將會覆蓋CMD指令的內(nèi)容并且附加 到ENTRYPOINT指令的參數(shù)中。
4. CMD可以是參數(shù),也可以是指令,ENTRYPOINT只能是命令;docker run 命令提供的運(yùn)行命令 參數(shù)可以覆蓋CMD,但不能覆蓋ENTRYPOINT。
5. 可以通過docker run --entrypoint 替換容器的入口程序
build arg
1. dockerfile 預(yù)定義參數(shù):HTTP_PROXY,http_proxy,HTTPS_PROXY,https_proxy, FTP_PROXY,ftp_proxy,NO_PROXY,no_proxy,ALL_PROXY,all_proxy。預(yù)定義參數(shù),可直 接在dockerfile中使用,無需使用arg來聲明
2.通過ARG自定義參數(shù)
FROM alpine:latest as s1 ARG wd label tag RUN echo $wd,$label,$tag ENV env1=env1value ENV env2=env2value MAINTAINER zloser LABEL $label $tag WORKDIR $wd COPY --from=stage0 /go/src/helloworld/app ./ EXPOSE 80 ENTRYPOINT ["./app","--param1=p1","--param2=p2"]
target與cache-from
對于多階段構(gòu)建,可以通過--target指定需要重新構(gòu)建的階段。--cache-from 可以指定一個鏡像作為緩存源,當(dāng)構(gòu)建過程中dockerfile指令與緩存鏡像源指令匹配,則直接使用緩存鏡像中的鏡像層,從而加快構(gòu)建進(jìn)程??梢詫⒕彺骁R像推送到遠(yuǎn)程注冊中心,提供給不同的構(gòu)建過程使用,在使用前需要先pull到本地。
onbuild
onbuild指令將指令添加到鏡像中,當(dāng)鏡像作為另一個構(gòu)建的基礎(chǔ)鏡像時,將觸發(fā)這些指令執(zhí)行。觸發(fā)指 令將在下游構(gòu)建的上下文中執(zhí)行。注意:onbuild指令不會影響當(dāng)前構(gòu)建,但會影響下游構(gòu)建
到此這篇關(guān)于dockerfile介紹與使用小結(jié)的文章就介紹到這了,更多相關(guān)dockerfile介紹與使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
通過Docker為本地DeepSeek-r1部署WebUI界面的完整教程
本文詳細(xì)介紹了如何通過Docker安裝并配置OpenWebUI,一個功能豐富的自托管Web用戶界面,用于與大型語言模型交互,文章步驟包括安裝Docker、配置WSL2、使用dockerrun命令部署OpenWebUI,并提供了詳細(xì)的命令解釋和部署結(jié)果,需要的朋友可以參考下2025-02-02
Docker部署MySQL并實(shí)現(xiàn)客戶端連接
這篇文章介紹了Docker部署MySQL并實(shí)現(xiàn)客戶端連接的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01
Docker容器化部署Spring?Boot項目實(shí)戰(zhàn)指南(最新整理)
本文給大家介紹Docker容器化部署Spring?Boot項目實(shí)戰(zhàn)指南,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧2026-02-02
Docker本地部署SSR前端項目實(shí)戰(zhàn)指南
本文介紹了Docker本地部署SSR前端項目實(shí)戰(zhàn)指南,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2026-01-01
Docker容器中Kingbase數(shù)據(jù)庫授權(quán)到期更換的解決方案
當(dāng)Docker容器內(nèi)的Kingbase數(shù)據(jù)庫授權(quán)文件(license.dat)到期后,會直接導(dǎo)致數(shù)據(jù)庫無法啟動、核心功能受限,本文結(jié)合官方鏡像特性與實(shí)操經(jīng)驗(yàn),整理了一套完整、可直接落地的授權(quán)更換與數(shù)據(jù)庫恢復(fù)方案,需要的朋友可以參考下2026-04-04
Docker Buildx鏡像壓縮的實(shí)現(xiàn)
本文主要介紹了Docker Buildx鏡像壓縮的實(shí)現(xiàn),顯著減小鏡像體積并提升構(gòu)建效率,適用于多平臺構(gòu)建、CI/CD流水線等場景,支持多架構(gòu)并行構(gòu)建與高效壓縮算法,優(yōu)化存儲與傳輸性能,降低部署成本,感興趣的可以了解一下2026-05-05
Docker在Ubuntu系統(tǒng)中的詳細(xì)操作指南
Docker 是一個開源的應(yīng)用容器引擎,允許開發(fā)者將應(yīng)用及其依賴打包在一個輕量級、可移植的容器中,實(shí)現(xiàn)快速部署和運(yùn)行,本文給大家詳細(xì)介紹了Docker在Ubuntu系統(tǒng)中的詳細(xì)操作指南,需要的朋友可以參考下2025-07-07
docker-compose啟動的容器一直處于restarting狀態(tài)的問題解決
本文主要介紹了docker-compose啟動的容器一直處于restarting狀態(tài)的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-11-11

