Docker 之 dockerfile製做鏡像

1  概述html

基於容器製做鏡像的問題是,每次都要啓動一個容器,在容器內部執行相關命令,才進行製做容器,這個比較麻煩。還有一種狀況,多是製做後的容器,容器變得很龐大,用戶拷貝也可能成問題,若是經過dockerfile,至關因而一個文檔,客戶能夠基於dockerfile生成新的容器nginx

dockerfile僅僅是用來製做鏡像的源碼文件,是構建容器過程當中的指令,docker可以讀取dockerfile的指定進行自動構建容器,基於dockerfile製做鏡像,每個指令都會建立一個鏡像層,即鏡像都是多層疊加而成,所以,層越多,效率越低,建立鏡像,層越少越好。所以能在一個指令完成的動做盡可能經過一個指令定義。docker

docker鏡像製做的工做邏輯shell

首先須要有一個製做鏡像的目錄,該目錄下有個文件,名稱必須爲Dockerfile,Dockerfile有指定的格式,#號開頭爲註釋,,指定默認用大寫字母來表示,以區分指令和參數,docker build讀取Dockerfile是按順序依次Dockerfile裏的配置,且第一條非註釋指令必須是FROM 開頭,表示基於哪一個基礎鏡像來構建新鏡像。能夠根據已存在的任意鏡像來製做新鏡像。apache

Dockerfile可使用環境變量,用ENV來定義環境變量,變量名支持bash的變量替換,如${variable:-word},表示若是變量值存在,就使用原來的變量,變量爲空時,就使用word的值做爲變量的值,通常使用這個表示法。ubuntu

${variable:+word},表示若是變量存在了,不是空值,那麼變量將會被賦予爲word對應的值,若是變量爲空,那麼依舊是空值vim

.dcokerignore:把文件路徑寫入到.dockerignore,對應的路徑將不會被打包到新鏡像centos

2  指令介紹

FROM 數組

 FROM指令是最重的一個且必須爲 Dockerfile文件開篇的第一個非註釋行,用於爲映像文件構建過程指定基準鏡像,後續的指令運行於此基準鏡像所提供的運行環境 .緩存

實踐中,基準鏡像能夠是任何可用鏡像文件,默認狀況下, docker build會在 docker主機上查找指定的鏡像文件,在其不存在時,則會從 Docker Hub Registry上拉取所需的鏡像文件 .若是找不到指定的鏡像文件, docker build會返回一個錯誤信息

FROM 語法

FROM <repository>[:<tag>] 或者 FROM <repository>@<digest>

<repository>:指定做爲base image的名稱

 <tag>base image的標籤,爲可選項,省略時默認爲 latest

<digest>爲校驗碼


MAINTANIER

用於讓鏡像製做者提供本人的詳細信息

Dockerfile並不限制 MAINTAINER指令可在出現的位置,但推薦將

其放置於 FROM指令以後 .

語法:

MAINTAINER  <authtor's detail> l <author's detail>但是任何文本信息,但約定俗成地使用做者名稱及郵件地址,如

MAINTAINER "sunny <sunny@ghbsunny.cn>"

通常把MAINTAINER放在FROM後面


COPY

用於從 Docker主機複製文件至建立的新映像文件

語法

COPY <src> ... <dest> . COPY ["<src>",... "<dest>"]

<src>:要複製的源文件或目錄,支持使用通配符

 <dest>:目標路徑,即正在建立的 image的文件系統路徑;建議爲 <dest>使用絕對路徑,<dest>絕對路徑爲鏡像中的路徑,而不是宿主機的路徑。不然, COPY指定則以 WORKDIR爲其起始路徑

注意:在路徑中有空白字符時,一般使用第二種格式 .

文件複製準則

<src>必須是build上下文中的路徑,即只能放在workshop這個工做目錄下,不能是其父目錄中的文件

若是<src>是目錄,其內部文件或者子目錄會被遞歸複製,但<src>目錄自身不會被複制

若是指定了多個<src>,或在<src>中使用了通配符,則<dest>必須是一個目錄,且dest目錄必須以/結尾

若是<dest>事先不存在,它將會被自動建立,這包括其父目錄路徑

copy是指在當前的workshop工做目錄中,準備好要添加到新鏡像的文件放到這個workshop下面,copy過程實際是基於dockerfile在後臺啓動一個容器,把工做目錄當作卷掛載到後臺啓動的容器,而後再把這些準備好的文件(workshop目錄下)拷貝到後臺容器,而後基於這個容器製做新鏡像,因此,鏡像的製做過程是基於指定的鏡像來製做

例子

建立一個目錄workshop,在該目錄下新建index.html文件用於鏡像製做的素材文件,在workshop下新建Dockerfile文件,把index.html拷貝到新鏡像裏

 

[root@docker ~]# mkdir workshop
[root@docker ~]# cd workshop/
[root@docker workshop]# vim index.html
[root@docker workshop]# vim Dockerfile
FROM busybox:1.27.2
 
MAINTAINER "sunny <sunny@ghbsunny.cn>"
 
COPY index.html  /data/htdocs/
COPY yum.repos.d /etc/yum.repos.d/

Dockerfile製做完成後,用命令build製做基於dockerfile的新鏡像。命令以下

[root@docker workshop]# docker build -t sunnydocker01:v1 ./

查看

docker images

查看到生成了一個新鏡像sunnydocker01

啓動新生成的鏡像,在容器內部有目錄/data/htdocs,而且有文件index.html,且成功拷貝/etc/yum.repos.d這個目錄到新鏡像中

[root@docker workshop]# docker run -it --rm --name sunny01 sunnydocker01:v1

/ # ls

bin   data  dev   etc   home  proc  root  sys   tmp   usr   var

/ # ls data/htdocs/

index.html

/ # ls /etc/yum.repos.d/

CentOS-Base.repo   docker-ce.repo     epel.repo

bak/               epel-testing.repo  sunny.repo

/ # ls /etc/yum.repos.d/

ADD 

ADD指令相似於 COPY指令, ADD支持使用 TAR文件和 URL路徑

語法

. ADD <src> ... <dest>

. ADD ["<src>",... "<dest>"]

.操做準則 .

COPY指令的4點準則

 若是<src>URL<dest>不以/結尾,則<src>指定的文件將被下載並直接被建立爲<dest>;若是<dest>/結尾,則文件名URL指定的文件將被直接下載,並保存爲<dest>/<filename>,注意,URL不能是ftp格式的url

若是<src>是一個本地系統上的壓縮格式的tar文件,它將被展開爲一個目錄,其行爲相似於「tar -x」命令,而後,經過URL獲取到的tar文件將不會自動展開

若是<src>有多個,或其間接或直接使用了通配符,則<dest>必須是一個以/結尾的目錄路徑;若是<dest>不以/結尾,則其被視做一個普通文件,<src>的內容將被直接寫入到<dest>

例子

在workshop目錄下,準備了apache-tomcat-8.0.47.tar.gz 這個tar包,已經從網絡上下載一個包,Dockerfile路徑以下

[root@docker workshop]# vim Dockerfile

 

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

COPY index.html  /data/htdocs/

COPY yum.repos.d /etc/yum.repos.d/

 

ADD http://nginx.org/download/nginx-1.14.0.tar.gz /tmp

ADD apache-tomcat-8.0.47.tar.gz /app/tomcat/

製做鏡像

[root@docker workshop]# docker build -t test02:v1 ./

基於新鏡像啓動容器,並檢查

[root@docker workshop]# docker run -it --rm --name testadd test02:v1

/ # ls

app   bin   data  dev   etc   home  proc  root  sys   tmp   usr   var

/ # ls /tmp/

nginx-1.14.0.tar.gz

/ # ls /app/tomcat/

apache-tomcat-8.0.47

/ #

注意,此時url對應的nginx已經被下載到/tmp下,且這個nginx的tar包不會被展開,同時目錄/app/tomcat/下有一個tomcat目錄,爲apache-tomcat-8.0.47.tar.gz 展開的目錄

 

WORKDIR

workdir爲工做目錄,指當前容器環境的工做目錄,用於爲 Dockerfile中全部的 RUNCMDENTRYPOINTCOPY ADD指定設定工做目錄

語法

 WORKDIR  <dirpath>

Dockerfile文件中, WORKDIR指令可出現屢次,其路徑也能夠爲相對路徑,不過,其是相對此前一個 WORKDIR指令指定的路徑

另外, WORKDIR也可調用由 ENV指定定義的變量 .例如

WORKDIR /var/log

WORKDIR  $STATEPATH

例子

指定workdir爲/usr/local,至關因而容器啓動後,會把工做目錄切換到/usr/local這個workdir路徑下,而不是默認的根目錄,以下例子,則相對路徑 ./src/ 的絕對路徑爲容器的/usr/local/src,製做鏡像時,把nginx包拷貝到/usr/local/src,把tomcat包解壓到/usr/local/src下面

[root@docker workshop]# vim Dockerfile

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

WORKDIR "/usr/local"

 

ADD http://nginx.org/download/nginx-1.14.0.tar.gz  ./src/

ADD apache-tomcat-8.0.47.tar.gz ./

啓動容器並檢查

[root@docker workshop]# docker run -it --rm --name testworkdir testworkdir:v1

/usr/local # ls

apache-tomcat-8.0.47  src

/usr/local # ls src

nginx-1.14.0.tar.gz

/usr/local #

容器啓動後,工做路徑直接切換爲/usr/local

 

 

VOLUME

定義卷,只能是docker管理的卷,,VOLUME爲容器上的目錄,用於在 image中建立一個掛載點目錄,以掛載 Docker host上的卷或其它容器上的卷

語法

. VOLUME <mountpoint>

. VOLUME ["<mountpoint>"]

若是掛載點目錄路徑下此前在文件存在, docker run命令會在卷掛載完成後將此前的全部文件複製到新掛載的卷中

例子

[root@docker workshop]# vim Dockerfile

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

VOLUME "/test/htdocs"

 

COPY  index.html  /test/htdocs/

製做鏡像

[root@docker workshop]# docker build -t testvolume:v1

啓動鏡像

[root@docker workshop]# docker run -it --rm --name testvolume1 testvolume:v1

/ # ls

bin   dev   etc   home  proc  root  sys   test  tmp   usr   var

/ # ls /test/htdocs/

index.html

/ #

在另外的窗口檢查該容器掛載的卷

[root@docker workshop]# docker inspect -f {{.Mounts}} testvolume1

[{volume e87fdd9ab3b8037167e23edb5c4eae3cc7c5d5ffa63c7a4fa4c18173e0e06460 /var/lib/docker/volumes/e87fdd9ab3b8037167e23edb5c4eae3cc7c5d5ffa63c7a4fa4c18173e0e06460/_data /test/htdocs local  true }]

[root@docker workshop]# cd /var/lib/docker/volumes/e87fdd9ab3b8037167e23edb5c4eae3cc7c5d5ffa63c7a4fa4c18173e0e06460/_data

[root@docker _data]# ls

index.html

[root@docker _data]# cat index.html

hello,this is first container made by sunny~

[root@docker _data]#

 

 

EXPOSE

暴露指定端口,用於爲容器打開指定要監聽的端口以實現與外部通訊

語法

EXPOSE <port>[/<protocol>] [<port>[/<protocol>] ...] l

其中<protocol>用於指定傳輸層協議,可爲 tcpudp兩者之一,默認爲 TCP協議

EXPOSE指令可一次指定多個端口,可是不能指定暴露爲宿主機的指定端口,由於指定的宿主機端口可能已經被佔用,所以這裏使用隨機端口,例如

. EXPOSE 11211/udp 11211/tcp

例子

[root@docker workshop]# vim Dockerfile

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

VOLUME "/data/htdocs"

 

COPY  index.html  /data/htdocs/

 

EXPOSE 80/tcp

製做鏡像

[root@docker workshop]# docker build -t testexpose:v1 ./

啓動並暴露端口,注意,啓動容器要跟大寫P選項-P來暴露

[root@docker workshop]# docker run -it -P --rm --name testexpose testexpose:v1

/ # ls

bin   data  dev   etc   home  proc  root  sys   tmp   usr   var

/ # ls data/htdocs/

index.html

/ #

在其餘端口檢查80口是否有暴露

[root@docker _data]# docker port testexpose

80/tcp -> 0.0.0.0:32768

[root@docker _data]#

 

 

ENV

ENV用於爲鏡像定義所需的環境變量,並可被 Dockerfile文件中位於其後的其它指令(如 ENVADDCOPY等)所調用 ,即先定義後調用

調用格式爲 $variable_name${variable_name}

語法

ENV <key> <value> . ENV <key>=<value> ... .

第一種格式中, <key>以後的全部內容均會被視做其 <value>的組成部分,所以一次只能設置一個變量

第二種格式,可用一次設置多個變量,每一個變量爲一個「<key>=<value>」的鍵值對,若是<value>包含空格,能夠以反斜線(\)進行轉義,也可經過對<value>加引號進行標識;另外反斜線也能夠用於續行;

.定義多個變量時,建議使用第二種方式,以便在同一層中完成全部功能

例子

下載一個nginx包,其中nginx的版本和nginx包的路徑用變量替換

編輯Dockerfile

vim Dockerfile

 

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

ADD ${nginx_url} /usr/local/

建立鏡像

[root@docker workshop]# docker build -t testenv:v1 ./

運行容器並驗證

[root@docker workshop]# docker run -it --rm --name testenv testenv:v1

/ # ls /usr/local/

nginx-1.14.0.tar.gz

/ #

有些變量在運行爲容器時依然有用,所以須要把那些變量在運行爲容器時從新定義爲一個新的值,若是變量不少,能夠放到一個文件中進行定義,使用參數 --env-list實現,經過文件來加載環境變量

 

RUN

RUN用於指定 docker build過程當中運行的程序,其能夠是任何命令,可是這裏有個限定,通常爲基礎鏡像能夠運行的命令,如基礎鏡像爲centos,安裝軟件命令爲yum而不是ubuntu裏的apt-get命令

RUN和CMD均可以改變容器運行的命令程序,可是運行的時間節點有區別,RUN表示在docker build運行的命令,而CMD是將鏡像啓動爲容器運行的命令。由於一個容器正常只用來運行一個程序,所以CMD通常只有一條命令,若是CMD配置多個,則只有最後一條命令生效。而RUN能夠有多個。

語法

RUN <command> . RUN ["<executable>", "<param1>", "<param2>"]

第一種格式中,<command>一般是一個shell命令,且以「/bin/sh -c」做爲父進程來運行它,這意味着此進程在容器中的PID不爲1,不能接收Unix信號,所以,當使用 docker stop <container>命令中止容器時,此進程接收不到SIGTERM信號;

第二種語法格式中的參數是一個JSON格式的數組,其中<executable>爲要運行的命令,後面的<paramN>爲傳遞給命令的選項或參數;然而,此種格式指定的命令不會以「/bin/sh -c」來發起,表示這種命令在容器中直接運行,不會做爲shell的子進程,所以常見的shell操做如變量替換以及通配符(?,*等)替換將不會進行,不過,若是要運行的沒能力依賴此shell特性的話,能夠將其替換爲相似下面的格式

RUN ["/bin/bash","-C","<executable>","<paraml>"]

例子

把下載的nginx打包文件,用RUN命令來展開

編輯dockerfile

vim Dockerfile

 

FROM busybox:1.27.2

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

WORKDIR "/usr/local/src"

 

ADD ${nginx_url} /usr/local/src/

RUN tar xf nginx-${nginx_ver}.tar.gz

建立鏡像

[root@docker workshop]# docker build -t testrun ./

運行容器並驗證

[root@docker workshop]# docker run -it --rm --name testrun testrun:latest

/usr/local/src # ls

nginx-1.14.0         nginx-1.14.0.tar.gz

/usr/local/src #

若是RUN的命令不少,就用&&符號鏈接多個命令,少構建鏡像層,提升容器的效率

例子以下

基礎鏡像爲centos,RUN多個命令

因爲安裝是到互聯網上的倉庫進行安裝,因此,建議把centos的yum源配置爲本地,即建立鏡像時,把yum的配置有本地倉庫源配置在CentOS-Base.repo文件放在workshop下面,配置文件配置ADD拷貝一份到新建鏡像的/etc/yum.repos.d目錄下,由於常常默認會優先加載CentOS-Base.repo下的包,可是不建議使用這個方法,除非本地倉庫有足夠的包解決依賴關係,不然建議僅使用默認的便可

編輯dockerfile

[root@docker workshop]# vim Dockerfile

 

FROM centos:7.3.1611

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

WORKDIR "/usr/local/src"

 

ADD CentOS-Base.repo  /etc/yum.repos.d/

ADD ${nginx_url} /usr/local/src/

RUN tar xf nginx-${nginx_ver}.tar.gz && yum -y install gcc pcre-devel openssl-devel make \

    && cd nginx-${nginx_ver} && ./configure && make && make install

建立鏡像

[root@docker workshop]# docker build -t nginx:v1 ./

運行容器,啓動nginx進程

[root@docker workshop]# docker build -t testexpose:v1 ./cc^C

[root@docker workshop]# docker run -it --rm --name nginxv1 nginx:v1

[root@ccedfdf5e63f src]# /usr/local/nginx/sbin/nginx

此時,nginx進程運行於後臺,不建議這麼作,由於容器的進程要運行於前臺模式,不然容器會終止,nginx運行於前臺,須要在nginx的配置文件nginx.conf裏添加配置項

vi /usr/local/nginx/conf/nginx.conf

daemon off;

這樣使得nginx運行於前臺

再次運行nginx,則運行於前臺

或者經過-g選項,在運行nginx的全局配置模式以後再運行某些參數,注意off後面的冒號

[root@ccedfdf5e63f local]# /usr/local/nginx/sbin/nginx -g "daemon off;"

 

 

CMD 

相似於 RUN指令, CMD指令也可用於運行任何命令或應用程序,不過,兩者的運行時間點不一樣 . RUN指令運行於映像文件構建過程當中,而 CMD指令運行於基於 Dockerfile構建出的新映像文件啓動一個容器時 . CMD指令的首要目的在於爲啓動的容器指定默認要運行的程序,且其運行結束後,容器也將終止;不過, CMD指定的命令其能夠被 docker run的命令行選項所覆蓋 .Dockerfile中能夠存在多個 CMD指令,但僅最後一個會生效

語法

CMD <command>或

CMD ["<executable>","<param1>","<param2>"]或

CMD["<param1>","<param2>"]

.前兩種語法格式的意義同 RUN

.第三種則用於爲 ENTRYPOINT指令提供默認參數

例子

編譯安裝nginx,並將鏡像的默認命令修改成nginx啓動於前臺,暴露80口

編輯dockerfile

vim Dockerfile

FROM centos:7.3.1611

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

WORKDIR "/usr/local/src"

EXPOSE 80/tcp

ADD ${nginx_url} /usr/local/src/RUN tar xf nginx-${nginx_ver}.tar.gz && yum -y install gcc pcre-devel openssl-devel make \

    && cd nginx-${nginx_ver} && ./configure && make && make install

CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

製做鏡像

[root@docker workshop]# docker build -t nginx:v3 ./

啓動容器並測試

[root@docker workshop]# docker run -it --rm --name nginxv3 nginx:v3

測試,容器的ip 爲 172.17.0.2,獲得nginx的測試頁

[root@docker yum.repos.d]# curl 172.17.0.2

查看容器80口被暴露爲哪一個口

[root@docker yum.repos.d]# docker port nginxv3

80/tcp -> 0.0.0.0:32772

[root@docker yum.repos.d]# curl 10.10.10.72:32772

注意,CMD在dockerfile裏寫的命令,若是啓動容器的命令行裏執行命令,則會把dockerfile裏的命令覆蓋掉,以下,容器啓動後,執行/bin/bash,而不是啓動nginx於前臺

[root@docker workshop]# docker run -it --rm -P --name nginxv3 nginx:v3 /bin/bash

[root@5f2f4b930df3 src]# ss -ntlp

若是dockerfile指定的CMD不容許覆蓋,則使用ENTRYPOINT

 

ENTRYPOINT

相似 CMD指令的功能,用於爲容器指定默認運行程序,從而使得容器像是一個單獨的可執行程序

CMD不一樣的是,由 ENTRYPOINT啓動的程序不會被 docker run命令行指定的參數所覆蓋,並且,這些命令行參數會被看成參數傳遞給 ENTRYPOINT指定指定的程序 .不過, docker run命令的 --entrypoint選項的參數可覆蓋 ENTRYPOINT指令指定的程序

語法

ENTRYPOINT <command>

ENTRYPOINT ["<excutable>","<param1>","<param2>"]

docker run 命令傳入的命令參數會覆蓋CMD指令的內容而且附加到ENTRYPOINT命令最後作爲其參數使用 . Dockerfile文件中也能夠存在多個 ENTRYPOINT指令,但僅有最後一個會生效

例子

把上例中的CMD執行命令,改爲ENTRYPOINT

vim Dockerfile

 

FROM centos:7.3.1611

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

WORKDIR "/usr/local/src"

EXPOSE 80/tcp

ADD ${nginx_url} /usr/local/src/

RUN tar xf nginx-${nginx_ver}.tar.gz && yum -y install gcc pcre-devel openssl-devel make \

    && cd nginx-${nginx_ver} && ./configure && make && make install

ENTRYPOINT ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

製做鏡像

[root@docker workshop]# docker build -t nginx:v5 ./

因爲此次鏡像修改相比上次不多,只差了一層CMD,構建過程直接使用緩存,因此速度很快,dockerfile裏,建議CMD和ENTRYPOINT不用複用,兩者選其一,除非明確指定CMD裏的命令參數會被ENTRYPOINT當作參數執行

啓動容器

run命令不帶其餘命令

[root@docker workshop]# docker run -it --rm -P --name nginxv3 nginx:v5

直接啓動,能夠正常啓動nginx,並暴露端口

run命令修改默認命令如/bin/bash,與上例CMD不同,此時報選項錯誤,由於此時會把 /bin/bash當作參數傳遞給ENTRYPOINT指定的指令,此時ENTRYPOINT指定的指令爲啓動nginx,不能識別/bin/bash

[root@docker workshop]# docker run -it --rm -P --name nginxv3 nginx:v5 /bin/bash

nginx: invalid option: "/bin/bash"

[root@docker workshop]#

可是,若是必定要覆蓋dockerfile裏指定的ENTRYPOINT命令,那麼在run命令使用參數--entrypoint來覆蓋,以下

[root@docker workshop]# docker run -it --rm -P --name nginxv3  --entrypoint /bin/bash nginx:v5

[root@4c940d422f20 src]# pwd

/usr/local/src

[root@4c940d422f20 src]#

成功以進程/bin/bash啓動了容器,覆蓋了dockerfile裏設定的nginx啓動命令

 

USER

USER用於指定運行 image時的或運行 Dockerfile中任何 RUNCMDENTRYPOINT指令指定的程序時的用戶名或 UID ,即改變容器中運行程序的身份

.默認狀況下, container的運行身份爲 root用戶

語法

USER  <UID>|<UserName>

須要注意的是, <UID>能夠爲任意數字,但實踐中其必須爲 /etc/passwd中某用戶的有效 UID,不然, docker run命令將運行失敗

 

ONBUILD

ONBUILD 用於在 Dockerfile中定義一個觸發器 . 用來指定運行docker指令

Dockerfile用於 build映像文件,此映像文件亦可做爲 base image被另外一個 Dockerfile用做 FROM指令的參數,並以之構建新的映像文件

.在後面的這個 Dockerfile中的 FROM指令在 build過程當中被執行時,將會觸發建立其 base imageDockerfile文件中的 ONBUILD指令定義的觸發器

語法

ONBUILD <INSTRUCTION>

儘管任何指令均可註冊成爲觸發器指令,可是ONBUILD不能自我嵌套,且不會觸發FROM和MAINTAINER指令

使用包含ONBUILD指令的Dockerfile構建的鏡像應該使用特殊的標籤,例如 ruby:2.0-onbuild

ONBUILD指令中使用ADDCOPY指令應該格外當心,由於新構建過程的上下文在缺乏指定的源文件時會失敗

ONBUILD 在構建鏡像時不會運行,是別人基於這個鏡像做爲基礎鏡像構建時,纔會運行

以下例子

增長一個ONBUILD命令,執行RUN

FROM centos:7.3.1611

 

MAINTAINER "sunny <sunny@ghbsunny.cn>"

 

ENV nginx_ver=1.14.0

ENV nginx_url=http://nginx.org/download/nginx-${nginx_ver}.tar.gz

 

WORKDIR "/usr/local/src"

EXPOSE 80/tcp

ADD ${nginx_url} /usr/local/src/

RUN tar xf nginx-${nginx_ver}.tar.gz && yum -y install gcc pcre-devel openssl-devel make \

    && cd nginx-${nginx_ver} && ./configure && make && make install

CMD ["/usr/local/nginx/sbin/nginx","-g","daemon off;"]

ONBUILD RUN echo -e "\nSunny do an onbuild~\n" >> /etc/issue

 

構建鏡像

[root@docker workshop]# docker build -t nginx:v6 ./

基於nginx:v6啓動容器,此時/etc/issue還沒寫入echo要插入的信息

[root@docker workshop]# docker run -it --rm -P --name nginxv3 nginx:v6 /bin/bash

[root@16e90f7a6460 src]# cat /etc/issue

\S

Kernel \r on an \m

 

[root@16e90f7a6460 src]#

而後基於這個nginx:v6鏡像,再次製做一個新鏡像,編輯一個新的Dockerfile

 

[root@docker ~]# mkdir nginxv7

[root@docker ~]# cd nginxv7/

[root@docker nginxv7]# vim Dockerfile

FROM nginx:v6

MAINTAINER "sunny <sunny@ghbsunny.cn>"

CMD "/bin/bash"

構建鏡像,注意,會提示執行一個build trigger,以下Executing 1 build trigger

[root@docker nginxv7]# docker build -t nginx:v7 ./

Sending build context to Docker daemon  2.048kB

Step 1/3 : FROM nginx:v6

# Executing 1 build trigger

 ---> Running in 6bb18c52af99

Removing intermediate container 6bb18c52af99

 基於新鏡像nginx:v7啓動新容器nginxv7

[root@docker nginxv7]# docker run -it --rm --name nginxv7 nginx:v7

[root@becc66948713 src]# cat /etc/issue

\S

Kernel \r on an \m

 

 

Sunny do an onbuild~

 

[root@becc66948713 src]#

此時,在舊的鏡像中的dockerfile裏的ONBUILD已經觸發,把信息寫入到/etc/issue裏

LABEL

LABEL爲磁盤映像文件添加元數據,能夠基於這個LABEL調用這些元數據,一個LABEL就是一堆k/v值,一個鏡像文件能夠有多個LABEL

相關文章
相關標籤/搜索