Docker關于Dockerfile的使用解讀
1. FROM
FROM指令用于指定其后構建新鏡像所使用的基礎鏡像。
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版本的基礎鏡像
多次使用FROM的情況時構建與運行分離的場景
基礎鏡像golang:1.10.3是非常龐大的,因為其中包含了所有的Go語言編譯工具和庫,而運行時候我們僅僅需要編譯后的server程序就行了,不需要編譯時的編譯工具,最后生成的大體積鏡像就是一種浪費。
scratch 是內置關鍵詞,并不是一個真實存在的鏡像。 FROM scratch 會使用一個完全干凈的文件系統(tǒng),不包含任何文件。因為Go語言編譯后不需要運行時,也就不需要安裝任何的運行庫。FROM scratch可以使得最后生成的鏡像最小化,其中只包含了server 程序。
當然,你也可以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 # 從編譯階段的中拷貝編譯結果到當前鏡像中 COPY --from=0 /build/server / ENTRYPOINT ["/server"]
COPY 指令的--from=0 參數(shù),從前邊的階段中拷貝文件到當前階段中,多個FROM語句時,0代表第一個階段。
除了使用數(shù)字,我們還可以給階段命名,比如:
# 編譯階段 命名為 builder FROM golang:1.10.3 as builder # ... 省略 # 運行階段 FROM scratch # 從編譯階段的中拷貝編譯結果到當前鏡像中 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同樣用于復制構建環(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只會復制構建目錄下的文件,不能使用URL也不會進行解壓操作。
3. ADD
ADD用于復制構建環(huán)境中的文件或目錄到鏡像中。
ADD <src>... <dest> ADD ["<src>",... "<dest>"]
<src>指定源文件位置,<dest>來指定目標位置。<src>可以是一個構建上下文中的文件或目錄,也可以是一個URL,但不能訪問構建上下文之外的文件或目錄。
ADD復制一個網(wǎng)絡文件:
ADD http://wordpress.org/test.zip $WORKER_PATH
另外,如果使用的是本地歸檔文件(gzip、bzip2、xz)時,Docker會自動進行解包操作,類似使用tar -x
4. RUN
RUN用于在鏡像容器中執(zhí)行命令,其有以下兩種命令執(zhí)行方式:
shell執(zhí)行
在這種方式會在shell中執(zhí)行命令,Linux下默認使用/bin/sh -c,Windows下使用cmd /S /C。
注意:通過SHELL命令修改RUN所使用的默認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)建的中間鏡像會被緩存,并會在下次構建中使用。
如果不想使用這些緩存鏡像,可以在構建時指定–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用于指定鏡像構建時所要執(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指定的程序都會被設置為默認程序。
ENTRYPOINT有以下兩種形式:
ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2
- ENTRYPOINT與CMD非常類似,不同的是通過docker run執(zhí)行的命令不會覆蓋 ENTRYPOINT
- docker run命令中指定的任何參數(shù),都會被當做參數(shù)再次傳遞給ENTRYPOINT。
- Dockerfile中只允許有一個ENTRYPOINT命令,多指定時會覆蓋前面的設置,而只執(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"]
構建
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服務器" by="ghostwritten"
也可以換行
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
docker inspect查看:
$ docker inspect itbilu/test
"Labels": {
"version": "1.0",
"description": "這是一個Web服務器",
"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導出的所有端口。
9. ENV
ENV用于設置環(huán)境變量,其有以下兩種設置形式:
ENV <key> <value> ENV <key>=<value> ...
示例:
ENV $WORKER_PATH /myapp
設置后,這個環(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)建掛載點,即向基于所構建鏡像創(chuàng)始的容器添加卷:
VOLUME ["/data"]
一個卷可以存在于一個或多個容器的指定目錄,該目錄可以繞過聯(lián)合文件系統(tǒng),并具有以下功能:
- 卷可以容器間共享和重用
- 容器并不一定要和其它容器共享卷
- 修改卷后會立即生效
- 對卷的修改不會對鏡像產生影響
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用于在容器內設置一個工作目錄:
WORKDIR /path/to/workdir
通過WORKDIR設置工作目錄后,Dockerfile中其后的命令RUN、CMD、ENTRYPOINT、ADD、COPY等命令都會在該目錄下執(zhí)行。
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
pwd最終將會在/a/b/c目錄中執(zhí)行。
docker run運行容器時,可以通過-w參數(shù)覆蓋構建時所設置的工作目錄。
13. ARG
ARG用于指定傳遞給構建運行時的變量:
ARG <name>[=<default value>]
示例:
ARG site ARG build_user=ghostwritten
以上我們指定了site和build_user兩個變量,其中build_user指定了默認值。
在使用docker build構建鏡像時,可以通過--build-arg <varname>=<value>參數(shù)來指定或重設置這些變量的值。
$ docker build --build-arg site=ghostwritten -t ghostwritten/test .
14. ONBUILD
ONBUILD用于設置鏡像觸發(fā)器:
ONBUILD [INSTRUCTION] ONBUILD ADD . /app/src ONBUILD RUN /usr/local/bin/python-build --dir /app/src
當所構建的鏡像被用做其它鏡像的基礎鏡像,該鏡像中的觸發(fā)器將會被鑰觸發(fā)。
示例:
第一個構建鏡像的Dockerfile,文件名為base.df
FROM busybox:latestWORKDIR /appRUN touch /app/base-evidenceONBUILD RUN ls -al /app
構建
docker build -t ghostwritten/onbuild:v1.0 -f base.df .
第二個構建鏡像的Dockerfile,文件名downstream.df
FROM ghostwritten/onbuild:v1.0 RUN touch downstream-evidence RUN ls -al .
構建
docker build -t ghostwritten/onbuild_down:v1.0 -f downstream.df .
onbuild指令在第一次構建時不會執(zhí)行,在第二次被引用時會首先執(zhí)行。
15. STOPSIGNAL
STOPSIGNAL用于設置停止容器所要發(fā)送的系統(tǒng)調用信號:
STOPSIGNAL signal
所使用的信號必須是內核系統(tǒng)調用表中的合法的值,如:9、SIGKILL。
16. SHELL
SHELL用于設置執(zhí)行命令(shell式)所使用的的默認shell類型:
SHELL ["executable", "parameters"]
SHELL在Windows環(huán)境下比較有用,Windows下通常會有cmd和powershell兩種shell,可能還會有sh。
這時就可以通過SHELL來指定所使用的shell類型。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
在Linux Ubuntu系統(tǒng)上使用Docker部署Android模擬器的操作指南
大家好,今天要給大家?guī)硪粋€超級實用的教程:如何在Linux Ubuntu系統(tǒng)上使用Docker部署Android模擬器,并結合cpolar內網(wǎng)穿透工具實現(xiàn)遠程訪問,需要的朋友可以參考下2025-03-03
Docker安裝ElasticSearch和Kibana的問題及處理方法
這篇文章主要介紹了Docker安裝ElasticSearch和Kibana的問題及遇到問題解決方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02

