0 什麼是 Dockerfile?
Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。
1 FROM
定製的鏡像都是基於 FROM 的鏡像,後續的操作都是基於該 image。
FROM scratch製作base imageFROM centos使用base imageFROM ubuntu:14.04最佳實踐
考慮安全性,請儘量使用官方 image 作為 base image。
2 LABEL
LABEL maintainer= "javaedge@gmail.com'LABEL version="1.O"LABEL description="This is a description"最佳實踐
這就像代碼的注釋,必須寫好元數據。
3 RUN
用於執行後面跟著的命令行命令。有以下倆種格式:
Shell格式
RUN apt-get install -y vimCMD echo "hello docker"ENTRYPOINT echo "hello docker"Dockerfile
docker build -t javaedge/centos-shell .
docker image lsdocker run javaedge/centos-shell
RUN <命令行命令># <命令行命令> 等同於,在終端操作的 shell 命令。Exec 格式
RUN [ "apt-get" , "install" , "-y", "vim" ]CMD [ " /bin/echo" , "hello docker" ]ENTRYPOINT [ "/bin/echo" , "hello docker" ]Dockerfile2
那如何修改才能讓 exec 格式的命令能被 shell 識別呢,修正:
RUN ["可執行文件", "參數1", "參數2"]# 例如:# RUN ["./test.php", "dev", "offline"] 等價於 RUN ./test.php dev offlineRUN yum update && yum install -y vim \ python-dev # 反斜線換行RUN apt-get update && apt-get install -y perl \ pwgen --no-install-recommends && rm -rf \ /var/lib/apt/lists/* # 注意清理cacheRUN /bin/bash -C 'source $HOME/.bashrc; echo$HOME'Dockerfile 的指令每執行一次都會在 docker 上新建一層。所以過多無意義的層,會造成鏡像膨脹過大。例如:
FROM centosRUN yum install wgetRUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"RUN tar -xvf redis.tar.gz以上執行會創建 3 層鏡像。可簡化為以下格式:FROM centosRUN yum install wget \ && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \ && tar -xvf redis.tar.gz如上,以 && 符號連接命令,這樣執行後,只會創建 1 層鏡像。
最佳實踐
可讀性複雜RUN用反斜線換行避免無用分層合併多條命令成一行4 WORKDIR
類似 linux 的cd 命令。
WORKDIR /test # 如果沒有會自動創建test目錄WORKDIR demoRUN pwd # 輸出結果應為/test/demo最佳實踐
使用WORKDIR,不要用 RUN cd儘量使用絕對目錄而非相對目錄。
5 ADD & COPY
COPY
複製指令,從上下文目錄中複製文件或者目錄到容器裡指定路徑。
格式:
COPY [--chown=<user>:<group>] <源路徑1>... <目標路徑>COPY [--chown=<user>:<group>] ["<源路徑1>",... "<目標路徑>"][--chown=<user>:<group>]:可選參數,用戶改變複製到容器內文件的擁有者和屬組。
<源路徑>:源文件或者源目錄,這裡可以是通配符表達式,其通配符規則要滿足 Go 的 filepath.Match 規則。例如:
COPY hom* /mydir/COPY hom?.txt /mydir/<目標路徑>:容器內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動創建。
ADD
ADD 指令和 COPY 的使用格式一致(同樣需求下,官方推薦使用 COPY)。功能也類似,區別:
ADD 的優點在執行 <源文件> 為 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,會自動複製並解壓到 <目標路徑>。ADD 的缺點在不解壓的前提下,無法複製 tar 壓縮文件。會令鏡像構建緩存失效,從而可能會令鏡像構建變得比較緩慢。具體是否使用,可以根據是否需要自動解壓來決定。ADD hello /# 添加到根目錄並解壓ADD test.tar.gz / WORKDIR /rootADD hello test/ # /root/test/helloWORKDIR /rootCOPY hello test/最佳實踐
大部分情況,COPY優先於ADDADD比COPY多個解壓功能添加遠程文件/目錄請使用curl或者wget
6 ENV
ENV MYSQL VERSION 5.6# 設置常量RUN apt-get install -y mysql-server= "$(MYSQL_VERSION]" \ && rm -rf /var/lib/apt/lists/* # 引用常量最佳實踐
儘量使用,可增加項目的可維護性。
7 上下文路徑
指令最後一個 . 是上下文路徑
上下文路徑指 docker 在構建鏡像,有時候想要使用到本機的文件(比如複製),docker build 命令得知這個路徑後,會將路徑下的所有內容打包。由於 docker 的運行模式是 C/S。我們本機是 C,docker 引擎是 S。實際的構建過程是在 docker 引擎下完成的,所以這個時候無法用到我們本機的文件。這就需要把我們本機的指定目錄下的文件一起打包提供給 docker 引擎使用。如果未說明最後一個參數,那麼默認上下文路徑就是 Dockerfile 所在的位置。
上下文路徑下不要放無用的文件,因為會一起打包發送給 docker 引擎,如果文件過多會造成過程緩慢。
VOLUME & EXPOSE
存儲和網絡
CMD & ENTRYPOINT
實戰
項目源碼
python app.py
如何調試Dockerfile?比如執行到如下步驟時報錯
那就進入該臨時中轉鏡像即可docker run -it 4320f8b526bc /bin/bash進入後,直接查看 app,原來是個文件,並非路徑!檢查下 Dockerfile
注意那行意思是將 app.py 放到根目錄下並命名為 app,所以它不是個目錄。
之後再 build,run 即可。
參考
更多最佳實踐,盡在官方 Dockerfile 文件https://github.com/docker-libraryhttps://docs.docker.com/engine/reference/builder/