在上一篇文章寫給後端的Docker初級入門教程:實戰篇最後咱們有提到用DockerFile來構建和定製屬於咱們本身的鏡像,由於時間和篇幅問題,上一篇文章對DockerFile只作了一個簡單的介紹和使用,並無對DockerFile具體的指令進行詳細的介紹和解釋,本篇,做爲上一篇實戰篇的額外補充篇,咱們將從DockerFile基礎的命令入手,一步一步的去構建一個屬於咱們本身的鏡像出來。java
Dockerfile是由一系列命令和參數構成的腳本,一個Dockerfile裏面包含了構建整個image的完整命令。Docker經過docker build執行Dockerfile中的一系列命令自動構建image。python
這裏咱們仍然選擇咱們上一篇使用的在centos基礎上定製咱們本身的鏡像爲本章的代碼實例,代碼以下:linux
FROM centos //繼承至centos
ENV mypath /tmp //設置環境變量
WORKDIR $mypath //指定工做目錄
RUN yum -y install vim //執行yum命令安裝vim
RUN yum -y install net-tools //執行yum命令安裝net-tools
EXPOSE 80 //對外默認暴露的端口是80
CMD /bin/bash //CMD 容器啓動命令,在運行容器的時候會自動執行這行命令,好比當咱們 docker run -it centos 的時候,就會直接進入bash
複製代碼
以後再經過docker build 命令編譯該DockerFile即可以獲得一個屬於本身的鏡像了。nginx
而後編譯該鏡像
docker build -f ./DockerFile -t mycentos:1.3.
-t 新鏡像名字:版本
-f 文件 -d 文件夾
複製代碼
運行該鏡像會發現vim和net-tools在咱們新的容器中已經能夠正常使用了。git
接下來呢,咱們將從FROM命令開始逐行介紹,最終完成對DockerFile經常使用命令的瞭解和掌握。程序員
既然咱們是在原有的centos鏡像的基礎上作定製,那麼咱們的新鏡像也必定是須要以centos這個鏡像爲基礎的,而FROM命令則表明了這個意思,在DockerFile中,基礎鏡像是必須指定的,FROM指令的做用就是指定基礎鏡像,所以一個DockerFile中,FROM是必備的指令,並且就像java,python的import關鍵字同樣,在DockerFile中,FROM指令必須放在第一條指令的位置github
固然,這個時候可能有朋友會問了,我要是不想在其餘的鏡像上定製鏡像怎麼辦呢,沒問題啊,Docker 提供了scratch 這個虛擬鏡像,若是你選擇 FROM scratch 的話,則意味着你不以任何鏡像爲基礎,接下來所寫的指令將做爲鏡像的第一層開始存在,固然,在某些狀況下,好比linux下靜態編譯的程序,運行的時候不須要操做系統提供運行時的支持,這個時候FROM scratch 是沒有問題的,反而會大幅下降咱們的鏡像體積。sql
功能:設置環境變量docker
一樣的,DockerFile也提供了兩種格式:shell
這個指令很簡單,就是設置環境變量而已,不管是後面的其它指令,如 RUN, 仍是運行時的應用,均可以直接使用這裏定義的環境變量。
能夠看到咱們示例中使用ENV設置mypath變量以後,在下一行WORKDIR則使用到了mypath這個變量
ENV mypath /tmp //設置環境變量
WORKDIR $mypath //指定工做目錄
複製代碼
功能,指定工做目錄
格式爲:WORKDIR 工做目錄路徑,若是這個目錄不存在的話,WORKDIR則會幫助咱們建立這個目錄。
設置過工做目錄以後,當咱們啓動容器,會直接進入該工做目錄
[root@8081304919c9 tmp]#
複製代碼
RUN 指令是用來執行命令行命令的。因爲命令行的強大能力,RUN 指令也是在定製鏡像時是較爲經常使用的指令之一。
RUN命令的格式一共有兩種,分別是:
Shell 格式
RUN 命令,就像直接在命令行中輸入命令同樣,好比RUN yum -y install vim就是使用的這種格式
exec 格式
RUN["可執行文件","參數1","參數2"],感受就像調用函數同樣
就像咱們在上一篇文章中說過的那樣,DockerFile中每一條指令都會創建一層,好比咱們上面執行過下面這條命令
RUN yum -y install vim
複製代碼
執行結束以後,則調用commit提交這一層的修改,使之構成一個新的鏡像,怎麼樣,是否是豁然開朗了呢。
並無
那好吧
一樣的,Dockerfile 支持 Shell 類的行尾添加 \ 的命令換行方式,以 及行首 # 進行註釋的格式。良好的格式,好比換行、縮進、註釋等,會讓維護、排障更爲容易,這是一個比較好的習慣。
提示:
若是使用apt方式安裝的話,最後不要忘記清理掉額外產生的apt緩存文件,若是不清理的話會讓咱們的鏡像顯得很是臃腫。由於DockerFile生成一層新的鏡像的時候,並不會刪除上一層鏡像所殘留的文件。
功能:聲明端口
格式: EXPOSE 端口1 端口2
EXPOSE 指令是聲明運行時容器提供服務端口,這固然只是一個聲明,在運行時並不會由於這個聲明應用就會開啓這個端口的服務。這樣聲明主要是爲了方便後期咱們配置端口映射。
以前介紹容器的時候曾經說過,Docker 不是虛擬機,容器就是進程。既然是進程,那麼在啓動容器的時候,須要指定所運行的程序及參數。CMD 指令就是用於指定默認的容器主進程的啓動命令的。
一樣的,DockerFile也爲咱們提供了兩種格式來使用CMD命令:
示例中,咱們使用的是第一種:
CMD /bin/bash
複製代碼
這條指令帶來的效果就是,當咱們經過run -it 啓動命令的時候,容器會自動執行/bin/bash,centos默認也是CMD /bin/bash,因此當咱們運行centos鏡像的時候,會自動進入bash環境裏面。
固然,咱們也能夠經過運行時指定命令的方式來體換默認的命令,好比:
docker run -it centos cat /etc/os-release
複製代碼
這樣當咱們運行鏡像的時候,cat /etc/os-release就會替代默認的CMD /bin/bash 輸出系統的版本信息了。
若是使用 shell 格式的話, 實際的命令會被包裝爲 sh -c 的參數的形式進行執行。
好比:
CMD echo $HOME
複製代碼
在實際執行中,會將其變動爲
CMD [ "sh", "-c", "echo $HOME" ]
複製代碼
固然還有不少初學者特別容易犯的問題,就是去啓動後臺服務,好比:
CMD service nginx start
複製代碼
這樣子去用,會發現容器運行了一會就自動退出了。
因此,?????
咱們以前不止一次的提醒過,容器不是虛擬機,容器就是進程,容器內的應用都應該之前臺運行,而不是像虛擬機,物理機那樣去運行後臺服務,容器就是爲了主進程而存在的,主進程退出,容器就失去了存在的意義,從而退出,其它輔助進程不是它須要關心的東西。
怎麼理解呢?想一想偶像劇,容器是女主角,主進程是男主角
你走了,我也不活了(撕心裂肺大哭),大概就是這麼個意思。
正如咱們前面所提出的,實際上CMD service nginx start 最終會被理解爲:
CMD [ "sh", "-c", "service nginx start"]
複製代碼
在這裏,咱們主進程實際就是sh,當咱們service nginx start執行完畢以後,那麼sh天然就會退出了,主進程退出,容器天然就會相應的中止。爭取的作法是直接執行nginx可執行文件,而且聲明之前臺的形式運行:
CMD ["nginx", "-g", "daemon off;"]
複製代碼
到這裏,咱們示例中所涉及到的命令已經講完了,固然,這並不夠,Docker中仍然有不少命令是咱們使用比較頻繁的,下面咱們的部分做爲補充,講一下其餘經常使用的DockerFile命令。
功能:複製文件
Docker依舊提供了兩種格式供咱們選擇:
到這裏你們其實會發現,Docker提供的兩種格式其實都是差很少的用法,一種相似於命令行,一種則相似於函數調用。
第一種例如(將package.json拷貝到/usr/src/app/目錄下):
COPY package.json /usr/src/app/
複製代碼
其次,目標路徑 能夠是容器內的絕對路徑,也能夠是相對於工做目錄的相對路徑 ,工做目錄能夠用 WORKDIR 指令來指定,若是須要改變文件所屬的用戶或者用戶組,能夠加上--chown 選項。
須要注意的是,使用 COPY 指 令,源文件的各類元數據都會保留。好比讀、寫、執行權限、文件變動時間等。這 個特性對於鏡像定製頗有用。
ADD命令能夠理解爲COPY命令的高級版,格式和用法與COPY幾乎一致,ADD在COPY的基礎上增長了一些功能,好比源路徑能夠是一個URL連接,當你這麼用的時候,Docker會嘗試着先將該URL表明的文件下載下來,而後複製到目標目錄上去,其餘的則是在COPY的基礎上增長了解壓縮之類的操做,碼字碼的手疼,須要瞭解的朋友能夠去官網查看相關的文檔,這裏我就不延申了。
在上一篇中,咱們有講容器卷這個概念,爲了防止運行時用戶忘記 將動態文件所保存目錄掛載爲卷,在 Dockerfile 中,咱們能夠事先指定某些 目錄掛載爲匿名卷,這樣在運行時若是用戶不指定掛載,其應用也能夠正常運 行,不會向容器存儲層寫入大量數據。
例如:
VOLUME /data
複製代碼
運行時經過-v參數便可以覆蓋默認的匿名卷設置。
功能:指定當前用戶
格式:USER 用戶名:用戶組
USER 指令和 WORKDIR 類似,都是改變環境狀態並影響之後的層。WORKDIR 是改變工做目錄,USER 則是改變以後層的執行 RUN, CMD 以及 ENTRYPOINT 這類命令的身份。固然,和 WORKDIR 同樣,USER 只是幫助你切換到指定用戶。
固然這個大前提是,你的User用戶是事先存在好的。
不知不覺間,Docker系列初級入門教程已經發到了第四篇,篇幅也到了一萬多字,前三篇文章加起來在掘金上慢慢有了大概1500左右的閱讀量,我知道這點對於不少掘金大佬來講只是微不足道的一點,但對於現階段的我來講已經很是知足了,歷來沒有想到過有一天本身也能夠經過分享去幫助到別人,正如我以前經過別人的技術博客學習那樣。
這個系列完結了嗎?我想初級篇應該是完結了,可是Nginx的初級入門教程,即將到來的Mysql,Netty等等並無,因爲目前還沒有畢業,尚未接受過工做的毒打(滑稽),因此只能盡本身的能力去寫一些基礎的入門教程,因此完結了嗎?並無,技術之路永無止境,只要咱們一直在堅持學習,我想,咱們能夠一直繼續下去。
感謝掘金,你們好,我是韓數,咱們下期文章再見!
最後,相關筆記已經同步開源至Github(歡迎star): github.com/hanshuaikan…
必定要記得給個star哦。
提早祝你們1024程序員節快樂!