作用
Dockerfile的內容是一坨可以執行的代碼(或者說是指令)(docker的DSL),這些代碼使得創建鏡像的操作可以復用以及自動化。
指令格式
Dockerfile的指令格式很簡單:
INSTRUCTION arguments
指令是不區分大小寫的,但是約定為全部大寫。
Dockerfile中指令的書寫順序就是它們的執行順序。
指令
FROM
Dockerfile必須以FROM指令開始,FROM指令指定了基礎鏡像是什么。也就是基於哪個鏡像來制作自己的鏡像。
FROM <image name>
image name的格式一般為"image:tag"
MAINTAINER
指定鏡像的作者信息:
MAINTAINER <author name>
RUN
在shell或者exec的環境下執行的命令。RUN指令會在新創建的鏡像上添加新的層面,接下來提交的結果用在Dockerfile的下一條指令中。
RUN <command>
ADD和COPY
復制文件指令。
ADD <source> <destination>
source可以是URL或者是啟動配置上下文中的一個文件。
將文件
所有拷貝到container中的文件和文件夾權限為0755,uid和gid為0
如果文件是可識別的壓縮格式,則docker會幫忙解壓縮。
- 如果要ADD本地文件,則本地文件必須在 docker build
,指定的 目錄下 - 如果要ADD遠程文件,則遠程文件必須在 docker build
,指定的 目錄下。比如:
docker build github.com/creack/docker-firefox
docker-firefox目錄下必須有Dockerfile和要ADD的文件。
COPY指令功能類似,但是COPY不允許source是URL,同時也不會進行解壓。
CMD和ENTRYPOINT
提供了容器默認的執行命令。 Dockerfile只允許使用一次CMD/ENTRYPOINT指令。 使用多個CMD/ENTRYPOINT會抵消之前所有的指令,只有最后一個指令生效。 CMD有三種形式:
CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD command param1 param2 (shell form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
區別:
第二種方式會以"/bin/sh -c"形式調用。第三種方式是為ENTRYPOINT指定參數,也就是使用第三種形式時,要有一個ENTRYPOINT指令。
如果在執行docker run時提供了command,且command和CMD中相同(參數可以不同),則會執行command,不執行CMD中的命令(實際含義就是把CMD中傳遞param覆蓋了)。
ENTRYPOINT(An ENTRYPOINT allows you to configure a container that will run as an executable)有兩種格式:
ENTRYPOINT ["executable", "param1","param2"] (exec form)
ENTRYPOINT command param1 param2 (shell form)
區別:
第二種(shell form)會屏蔽掉docker run時后面加的命令和CMD里的參數;第一種會把docker run后面的參數或CMD里的參數追加給ENTRYPOINT,docker run后面的參數會覆蓋掉CMD里的參數。
例如:
...
ENTRYPOINT ["echo", "param1"]
執行
docker run -it test param2
顯示param1 param2
如果是shell form形式,docker run提供的參數就無效。
兩者區別
ENTRYPOINT和CMD的不同點在於執行docker run時參數傳遞方式,CMD指定的命令可以被docker run傳遞的命令覆蓋,例如,如果用CMD指定:
...
CMD ["echo"]
然后運行
docker run CONTAINER_NAME echo foo
那么CMD里指定的echo會被新指定的echo覆蓋,所以最終相當於運行echo foo,所以最終打印出的結果就是:
foo
而ENTRYPOINT會把容器名后面的所有內容都當成參數傳遞給其指定的命令(不會對命令覆蓋),比如:
...
ENTRYPOINT ["echo"]
然后運行
docker run CONTAINER_NAME echo foo
則CONTAINER_NAME后面的echo foo
都作為參數傳遞給ENTRYPOING里指定的echo命令了,所以相當於執行了
echo "echo foo"
最終打印出的結果就是:
echo foo
另外,在Dockerfile中,ENTRYPOINT指定的參數比運行docker run時指定的參數更靠前,比如:
...
ENTRYPOINT ["echo", "foo"]
執行
docker run CONTAINER_NAME bar
相當於執行了:
echo foo bar
打印出的結果就是:
foo bar
EXPOSE
指定容器在運行時監聽的端口。
EXPOSE <port> [<port>...]
該指令會將容器中的端口映射成宿主機器中的某個端口。當你需要訪問容器的時候,可以不使用容器的IP地址而是使用宿主機器的IP地址和映射后的端口。要完成整個操作需要兩個步驟:
- 首先在Dockerfile使用EXPOSE設置需要映射的容器端口;
- 然后在運行容器的時候指定-p選項加上EXPOSE設置的端口,這樣EXPOSE設置的端口號會被隨機映射成宿主機器中的一個端口號。也可以指定需要映射到宿主機器的那個端口,這時要確保宿主機器上的端口號沒有被使用。
EXPOSE指令可以一次設置多個端口號,相應的運行容器的時候,可以配套的多次使用-p選項。
WORKDIR
切換目錄用,可以多次切換(相當於cd命令),對RUN,CMD,ENTRYPOINT生效。
WORKDIR /path/to/workdir
ENV
設置環境變量。
ENV <key> <value>
如果不指定value,表示清除key環境變量。
USER
使用哪個用戶跑container:
USER <uid>
VOLUME
授權訪問從容器內到主機上的目錄。語法如下:
VOLUME ["/data"]
參考文檔
Dockerfile reference
Docker入門教程(三)Dockerfile
Docker Dockerfile詳解
Docker學習筆記(3)-- 如何使用Dockerfile構建鏡像
Dockerfile里指定執行命令用ENTRYPOING和用CMD有何不同?
What is the difference between the COPY
and ADD
commands in a Dockerfile?