Docker關(guān)于Dockerfile的使用解讀
1. FROM
FROM指令用于指定其后構(gòu)建新鏡像所使用的基礎(chǔ)鏡像。
FROM <image> FROM <image>:<tag> FROM <image>:<digest>
- FROM必須是Dockerfile中第一條非注釋命令
- 在一個Dockerfile文件中創(chuàng)建多個鏡像時,docker17.05版本以后,F(xiàn)ROM可以多次出現(xiàn)。只需在每個新命令FROM之前,記錄提交上次的鏡像ID。
- tag或digest是可選的,如果不使用這兩個值時,會使用latest版本的基礎(chǔ)鏡像
多次使用FROM的情況時構(gòu)建與運行分離的場景
基礎(chǔ)鏡像golang:1.10.3
是非常龐大的,因為其中包含了所有的Go語言編譯工具和庫,而運行時候我們僅僅需要編譯后的server程序就行了,不需要編譯時的編譯工具,最后生成的大體積鏡像就是一種浪費。
scratch
是內(nèi)置關(guān)鍵詞,并不是一個真實存在的鏡像。 FROM scratch 會使用一個完全干凈的文件系統(tǒng),不包含任何文件。因為Go語言編譯后不需要運行時,也就不需要安裝任何的運行庫。FROM scratch可以使得最后生成的鏡像最小化,其中只包含了server 程序。
當(dāng)然,你也可以FROM一個你熟悉的并且空間占用小的鏡像,比如:centos、ubuntu、busybox
等。
# 編譯階段 FROM golang:1.10.3 COPY server.go /build/ WORKDIR /build RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server # 運行階段 FROM scratch # 從編譯階段的中拷貝編譯結(jié)果到當(dāng)前鏡像中 COPY --from=0 /build/server / ENTRYPOINT ["/server"]
COPY 指令的--from=0
參數(shù),從前邊的階段中拷貝文件到當(dāng)前階段中,多個FROM語句時,0代表第一個階段。
除了使用數(shù)字,我們還可以給階段命名,比如:
# 編譯階段 命名為 builder FROM golang:1.10.3 as builder # ... 省略 # 運行階段 FROM scratch # 從編譯階段的中拷貝編譯結(jié)果到當(dāng)前鏡像中 COPY --from=builder /build/server /
COPY --from
不但可以從前置階段中拷貝,還可以直接從一個已經(jīng)存在的鏡像中拷貝。
比如,
FROM ubuntu:16.04 COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
2. COPY
COPY同樣用于復(fù)制構(gòu)建環(huán)境中的文件或目錄到鏡像中。
COPY <src>... <dest> COPY ["<src>",... "<dest>"] COPY --from=builder /build/server / COPY --from=quay.io/coreos/etcd:v3.3.9 /usr/local/bin/etcd /usr/local/bin/
COPY指令非常類似于ADD,不同點在于COPY只會復(fù)制構(gòu)建目錄下的文件,不能使用URL也不會進行解壓操作。
3. ADD
ADD用于復(fù)制構(gòu)建環(huán)境中的文件或目錄到鏡像中。
ADD <src>... <dest> ADD ["<src>",... "<dest>"]
<src>
指定源文件位置,<dest>
來指定目標(biāo)位置。<src>
可以是一個構(gòu)建上下文中的文件或目錄,也可以是一個URL,但不能訪問構(gòu)建上下文之外的文件或目錄。
ADD復(fù)制一個網(wǎng)絡(luò)文件:
ADD http://wordpress.org/test.zip $WORKER_PATH
另外,如果使用的是本地歸檔文件(gzip、bzip2、xz)時,Docker會自動進行解包操作,類似使用tar -x
4. RUN
RUN用于在鏡像容器中執(zhí)行命令,其有以下兩種命令執(zhí)行方式:
shell執(zhí)行
在這種方式會在shell中執(zhí)行命令,Linux下默認(rèn)使用/bin/sh -c
,Windows下使用cmd /S /C
。
注意:通過SHELL命令修改RUN所使用的默認(rèn)shell
RUN <command>
RUN /bin/bash -c 'source $HOME/.bashrc; \ echo $HOME' #通過RUN執(zhí)行多條命令時,可以通過\換行執(zhí)行
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' #同一行中,通過分號分隔命令
exec執(zhí)行
RUN ["executable", "param1", "param2"]
RUN指令創(chuàng)建的中間鏡像會被緩存,并會在下次構(gòu)建中使用。
如果不想使用這些緩存鏡像,可以在構(gòu)建時指定–no-cache參數(shù),如:docker build --no-cache
。
5. CMD
CMD用于指定在容器啟動時所要執(zhí)行的命令。
CMD有以下三種格式:
CMD ["executable","param1","param2"] CMD ["param1","param2"] CMD command param1 param2
CMD不同于RUN,CMD用于指定在容器啟動時所要執(zhí)行的命令,而RUN用于指定鏡像構(gòu)建時所要執(zhí)行的命令。
CMD與RUN在功能實現(xiàn)上也有相似之處。
如:
docker run -t -i ghostwritten/web_server /bin/true
等價于:
cmd ["/bin/true"]
- CMD在Dockerfile文件中僅可指定一次,指定多次時,會覆蓋前的指令。
- docker run命令也會覆蓋Dockerfile中CMD命令。
6. ENTRYPOINT
ENTRYPOINT用于給容器配置一個可執(zhí)行程序。
也就是說,每次使用鏡像創(chuàng)建容器時,通過ENTRYPOINT指定的程序都會被設(shè)置為默認(rèn)程序。
ENTRYPOINT有以下兩種形式:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2
- ENTRYPOINT與CMD非常類似,不同的是通過docker run執(zhí)行的命令不會覆蓋 ENTRYPOINT
- docker run命令中指定的任何參數(shù),都會被當(dāng)做參數(shù)再次傳遞給ENTRYPOINT。
- Dockerfile中只允許有一個ENTRYPOINT命令,多指定時會覆蓋前面的設(shè)置,而只執(zhí)行最后的ENTRYPOINT指令。
docker run運行容器時指定的參數(shù)都會被傳遞給ENTRYPOINT
,且會覆蓋CMD命令指定的參數(shù)。
如,執(zhí)行docker run <image> -d
時,-d參數(shù)將被傳遞給入口點。
也可以通過docker run --entrypoint
重寫ENTRYPOINT入口點。
示例:
ENTRYPOINT ["/usr/bin/nginx"]
Dockerfile
FROM ubuntu:16.04 RUN apt-get update RUN apt-get install -y nginx RUN echo 'Hello World, 我是個容器' > /var/www/html/index.html EXPOSE 80 ENTRYPOINT ["/usr/sbin/nginx"]
構(gòu)建
docker build -t="ghostwritten/app" .
創(chuàng)建容器
docker run -i -t ghostwritten/app -g "daemon off;"
-g "daemon off;"
參數(shù)將會被傳遞給ENTRYPOINT
,最終在容器中執(zhí)行的命令為/usr/sbin/nginx -g "daemon off;"
。
7. LABEL
LABEL用于為鏡像添加元數(shù)據(jù),元數(shù)以鍵值對的形式指定:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
使用LABEL指定元數(shù)據(jù)時,一條LABEL指定可以指定一或多條元數(shù)據(jù),指定多條元數(shù)據(jù)時不同元數(shù)據(jù)之間通過空格分隔。
LABEL version="1.0" description="這是一個Web服務(wù)器" by="ghostwritten"
也可以換行
LABEL multi.label1="value1" \ multi.label2="value2" \ other="value3"
docker inspect查看:
$ docker inspect itbilu/test "Labels": { "version": "1.0", "description": "這是一個Web服務(wù)器", "by": "ghostwritten" },
注意: Dockerfile中還有個MAINTAINER
命令,該命令用于指定鏡像作者。
但MAINTAINER并不推薦使用,更推薦使用LABEL來指定鏡像作者。
如:
LABEL maintainer="ghostwritten"
8. EXPOSE
EXPOSE用于指定容器在運行時監(jiān)聽的端口:
EXPOSE <port> [<port>...]
EXPOSE并不會讓容器的端口訪問到主機。
要使其可訪問,需要在docker run運行容器時通過-p
來發(fā)布這些端口,或通過-P
參數(shù)來發(fā)布EXPOSE導(dǎo)出的所有端口。
9. ENV
ENV用于設(shè)置環(huán)境變量,其有以下兩種設(shè)置形式:
ENV <key> <value> ENV <key>=<value> ...
示例:
ENV $WORKER_PATH /myapp
設(shè)置后,這個環(huán)境變量在ENV命令后都可以使用。如:
WORKERDIR $WORKER_PATH
docker run可以通過 -e
新添環(huán)境變量或者覆蓋環(huán)境變量。
docker run -tid --name test -e $WORKER_PATH /web -e IP=192.168.1.2 ghostwritten/web:v1.0
-e $WORKER_PATH /web
為覆蓋ENV $WORKER_PATH /myapp
-e IP=192.168.1.2
為新添 10. VOLUME
VOLUME用于創(chuàng)建掛載點,即向基于所構(gòu)建鏡像創(chuàng)始的容器添加卷:
VOLUME ["/data"]
一個卷可以存在于一個或多個容器的指定目錄,該目錄可以繞過聯(lián)合文件系統(tǒng),并具有以下功能:
- 卷可以容器間共享和重用
- 容器并不一定要和其它容器共享卷
- 修改卷后會立即生效
- 對卷的修改不會對鏡像產(chǎn)生影響
VOLUME創(chuàng)建一個掛載點:
ENV WORKER_PATH /web VOLUME [$WORKER_PATH]
運行容器時,需-v
參將能本地目錄綁定到容器的卷(掛載點)上,以使容器可以訪問宿主機的數(shù)據(jù)。
docker run -itd --name web -v ~/data:/web/ ghostwritten/web:v1.0
11. USER
USER用于指定運行鏡像所使用的用戶
可以使用用戶名、UID或GID,或是兩者的組合。
USER user USER user:group USER uid USER uid:gid USER user:gid USER uid:group
docker run
運行容器時,可以通過-u
參數(shù)來覆蓋所指定的用戶。
12. WORKDIR
WORKDIR用于在容器內(nèi)設(shè)置一個工作目錄:
WORKDIR /path/to/workdir
通過WORKDIR設(shè)置工作目錄后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都會在該目錄下執(zhí)行。
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
pwd最終將會在/a/b/c目錄中執(zhí)行。
docker run運行容器時,可以通過-w
參數(shù)覆蓋構(gòu)建時所設(shè)置的工作目錄。
13. ARG
ARG用于指定傳遞給構(gòu)建運行時的變量:
ARG <name>[=<default value>]
示例:
ARG site ARG build_user=ghostwritten
以上我們指定了site和build_user兩個變量,其中build_user指定了默認(rèn)值。
在使用docker build構(gòu)建鏡像時,可以通過--build-arg <varname>=<value>
參數(shù)來指定或重設(shè)置這些變量的值。
$ docker build --build-arg site=ghostwritten -t ghostwritten/test .
14. ONBUILD
ONBUILD用于設(shè)置鏡像觸發(fā)器:
ONBUILD [INSTRUCTION] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
當(dāng)所構(gòu)建的鏡像被用做其它鏡像的基礎(chǔ)鏡像,該鏡像中的觸發(fā)器將會被鑰觸發(fā)。
示例:
第一個構(gòu)建鏡像的Dockerfile,文件名為base.df
FROM busybox:latestWORKDIR /appRUN touch /app/base-evidenceONBUILD RUN ls -al /app
構(gòu)建
docker build -t ghostwritten/onbuild:v1.0 -f base.df .
第二個構(gòu)建鏡像的Dockerfile,文件名downstream.df
FROM ghostwritten/onbuild:v1.0 RUN touch downstream-evidence RUN ls -al .
構(gòu)建
docker build -t ghostwritten/onbuild_down:v1.0 -f downstream.df .
onbuild指令在第一次構(gòu)建時不會執(zhí)行,在第二次被引用時會首先執(zhí)行。
15. STOPSIGNAL
STOPSIGNAL用于設(shè)置停止容器所要發(fā)送的系統(tǒng)調(diào)用信號:
STOPSIGNAL signal
所使用的信號必須是內(nèi)核系統(tǒng)調(diào)用表中的合法的值,如:9、SIGKILL。
16. SHELL
SHELL用于設(shè)置執(zhí)行命令(shell式)所使用的的默認(rèn)shell類型:
SHELL ["executable", "parameters"]
SHELL在Windows環(huán)境下比較有用,Windows下通常會有cmd和powershell兩種shell,可能還會有sh。
這時就可以通過SHELL來指定所使用的shell類型。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
docker安裝、調(diào)試qsign簽名服務(wù)器的解決方案
這篇文章主要介紹了docker安裝、調(diào)試qsign簽名服務(wù)器的解決方案,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-04-04docker容器狀態(tài)的轉(zhuǎn)換實現(xiàn)
這篇文章主要介紹了docker容器狀態(tài)的轉(zhuǎn)換實現(xiàn),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11安裝Docker時執(zhí)行yum?install?-y?yum-utils報錯解決辦法
在安裝工具時使用yum命令報錯,問題通常是服務(wù)器無法連接網(wǎng)絡(luò),解決此問題需配置鏡像源,文中通過代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價值,需要的朋友可以參考下2024-11-11docker之MySQL同步數(shù)據(jù)的實現(xiàn)
本文主要介紹了docker之MySQL同步數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Docker 數(shù)據(jù)管理Named volume詳解
這篇文章主要介紹了Docker 數(shù)據(jù)管理Named volume詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03Docker中的容器網(wǎng)絡(luò)和通信原理詳解
這篇文章主要介紹了Docker中的容器網(wǎng)絡(luò)和通信原理,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04