太長不讀版: 案例地址:https://github.com/gholly/docker-scaffold.gitjava
1. Dockerfile是什麼?git
Dockerfile是Docker用來構建鏡像的文本文件,包含自定義的指令和格式。能夠經過docker build命令從Dockerfile中構建鏡像.
2. 鏡像構建過程github
Dockerfile描述了組裝鏡像的步驟,其中每條指令都是單獨執行的。除了FROM指令,其餘每一條指令都會在上一條指令所生成鏡像的基礎上執行,執行完後會生成一個新的鏡像層,新的鏡像層覆蓋原來的鏡像之上從而造成了新的鏡像,Dockerfile所生成的最終鏡像就是在基礎鏡像上面疊加一層層的鏡像層組建的。spring
3. Dockerfile指令docker
在Dockerfile中,指令(INSTRUMENT)不區分大小寫,可是爲了與參數區分,推薦爲大寫。Docker會順序執行Dockerfile中的指令,第一條指令必須爲FROM指令,它用於制定構建鏡像的基礎鏡像。在Dockerfile中以#開頭的行爲註釋,而在其餘位置的#會被當成參數。shell
指令的格式以下:json
# comments INSTRUMENT argument
Dockerfile的指令有FROM,MAINTAINER,RUN,CMD,EXPOSE,ENV,ADD,COPY,ENTRYPOINT,VOLUMN,USER,WORKDIR,ONBUILD等數組
格式: ENV <key> <value> 或 ENV <key>=<value>
ENV 指令能夠爲鏡像建立出來的容器聲明環境變量,而且在Dockerfile文件,ENV指令聲明的環境變量會被後面的指定指令(即ENV,add,copy,workdir,expose,volume,user)解釋使用。其餘指令使用環境變量時,使用格式爲$variable_name 或${variable_name}.在變量前下\能夠轉義,如$foo或者${foo},都會被轉成$foo 和${foo},而不是環境變量所保存的值。另外,ONBUILD指令不支持環境替換。springboot
格式: FROM <image> 或 ENV <image>:<tag>
FROM指令的功能是爲後面的指令提供基礎鏡像,所以一個有效的Dockerfile必須以FROM指令做爲第一條非註釋指令。基礎鏡像能夠選取任何有效的鏡像。在一個dockerfile文件中,From指令能夠出現屢次,這樣會構建多個鏡像。在每個鏡像建立完成後,docker命令行會輸出該鏡像的ID。若from指令中tag參數爲空,則tag默認爲lastest;若參數image或tag指定的鏡像不存在,則返回錯誤。網絡
從公共鏡像庫拉取鏡像很容易?example中的鏡像來源是?
格式: COPY <src> <dest>
COPY指令複製<src>所指向的文件或目錄,將它添加到新鏡像中,複製的文件或目錄在鏡像中的路徑是<dest>.
格式: ADD <src> <dest>
add和copy指令功能類似,都支持複製本地文件到鏡像的功能,但add指令還支持其餘功能。<src>能夠是一個指向一個網絡文件的url,<dest>指向一個目錄,則url必須是徹底路徑,這樣能夠獲取該網絡文件的filename.
ADD http://example.com/foofile / #會建立文件/foofile
<src>還能夠指向一個本地壓縮歸檔文件,該文件在複製到容器中時會被解壓提取,如:
ADD example.tar.xz / #則建立example文件
但若網絡文件url中的文件是壓縮文件,則不會被解壓提取。 ADD和copy指令雖然功能類似,推薦使用copy,由於copy只支持本地文件,相比add更透明。
格式: RUN <command> #shell格式 RUN ["executable","param1","param2"] #exec格式,推薦格式
RUN指令會在前一條命令建立出的鏡像的基礎上建立一個容器,並在容器中運行命令,在命令結束後提交容器爲新鏡像,新鏡像被dockerfie中的下一條指令使用。
當使用exec格式時,命令是直接運行的,容器不調用shell 程序,即容器中沒有shell程序。exec格式中的參數會被當成json數組被docker解析,因此要使用雙引號。若但願運行shell程序,指令須要寫成這樣 CMD [ "sh", "-c", "echo" , "$HOME"]
格式: CMD <command> #shell格式 CMD ["executable","param1","param2"]#exec格式,推薦格式 CMD [param1","param2"]
CMD指令提供容器運行時的默認值,這些默認值能夠爲一條指令,也能夠是參數。一個dockerfie文件中能夠有多個cmd指令,只有最後一條生效。
CMD指令在構建鏡像時不執行任何指令,而是在容器啓動時默認將cmd的指令做爲第一條執行的命令。若是docker run命令時指定了命令參數,則會覆蓋cmd指令中的命令。
格式: ENTRYPOINT <command> #shell格式 ENTRYPOINT ["executable","param1","param2"]#exec格式,推薦格式
ENTRYPOINT指令與cmd命令類似,均可以讓容器在每次啓動的時候執行相同的命令。最後一條ENTRYPOINT生效。
當爲shell格式時,ENTRYPOINT會忽略掉任何cmd指令和docker run命令的參數,因此推薦exec格式。
使用exec格式時,docker run會覆蓋cmd的內容,而且附加到ENTRYPOINT的指令的參數中。
4. 根據以上指令實踐一下:嘗試把一個簡單的springboot項目打包成一個鏡像 Dcokerfile文件
# openjdk:lastest 可從https://hub.docker.com/官方鏡像倉庫去查找你想要的鏡像 FROM openjdk:latest COPY ./build/libs/scaffold-1.0-SNAPSHOT.jar docker-scaffold.jar #JAVA_OPTS 是用來設置JVM相關運行參數的變量 ENV JAVA_OPTS="" EXPOSE 8080 ENTRYPOINT ["java", "-jar", "docker-scaffold.jar"]
docker build -f ./Dockerfile . -t scaffold docker run scaffold #啓動鏡像 docker exec -it container-id sh 或者 docker exec -it container-id sh #進入到容器中 curl -i http://localhost:8080/hi
返回200,說明此時成功了。