ONBUILD指令可以為鏡像添加觸發器。其參數是任意一個Dockerfile 指令。
當我們在一個Dockerfile文件中加上ONBUILD指令,該指令對利用該Dockerfile構建鏡像(比如為A鏡像)不會產生實質性影響。
但是當我們編寫一個新的Dockerfile文件來基於A鏡像構建一個鏡像(比如為B鏡像)時,這時構造A鏡像的Dockerfile文件中的ONBUILD指令就生效了,在構建B鏡像的過程中,首先會執行ONBUILD指令指定的指令,然后才會執行其它指令。
需要注意的是,如果是再利用B鏡像構造新的鏡像時,那個ONBUILD指令就無效了,也就是說只能再構建子鏡像中執行,對孫子鏡像構建無效。其實想想是合理的,因為在構建子鏡像中已經執行了,如果孫子鏡像構建還要執行,相當於重復執行,這就有問題了。
利用ONBUILD指令,實際上就是相當於創建一個模板鏡像,后續可以根據該模板鏡像創建特定的子鏡像,需要在子鏡像構建過程中執行的一些通用操作就可以在模板鏡像對應的dockerfile文件中用ONBUILD指令指定。 從而減少dockerfile文件的重復內容編寫。
我們來看一個簡單例子。
1、先編寫一個Dockerfile文件,內容如下:
#test FROM ubuntu MAINTAINER hello ONBUILD RUN mkdir mydir
利用上面的dockerfile文件構建鏡像: docker build -t imagea .
利用imagea鏡像創建容器: docker run --name test1 -it imagea /bin/bash
我們發現test1容器的根目錄下並沒有mydir目錄。說明ONBUILD指令指定的指令並不會在自己的構建中執行。
2、再編寫一個新的Dockerfile文件,內容 如下
#test
FROM imagea
MAINTAINER hello1
注意,該構建准備使用的基礎鏡像是上面構造出的鏡像imagea
利用上面的dockerfile文件構建鏡像: docker build -t imageb .
利用imagea鏡像創建容器: docker run --name test2 -it imageb /bin/bash
我們發現test2容器的根目錄下有mydir目錄,說明觸發器執行了。 這個其實從構建imageb的輸出日志就可看出。日志如下:
xxx@ubuntu:~/myimage$ docker build -t imageb . Sending build context to Docker daemon 15.87 kB Step 1 : FROM imagea # Executing 1 build trigger... Step 1 : RUN mkdir mydir ---> Running in e16c35c94b03 ---> 4b393d1610a6 Removing intermediate container e16c35c94b03 Step 2 : MAINTAINER hello1 ---> Running in c7b0312516ea ---> 0f63b8e04d82 Removing intermediate container c7b0312516ea Successfully built 0f63b8e04d82
我們可以看出,FROM指令執行之后,就立即執行的是觸發器(ONBUILD指令指定的指令)