一掺逼,簡單介紹
docker鏡像構(gòu)建方式有兩種方式吃媒,第一種是啟動(dòng)基礎(chǔ)容器之后,進(jìn)入容器安裝所需要的文件吕喘,配置赘那,變量等,完成后使用docker commit提交成為一個(gè)新的鏡像氯质,第二種則是通過編寫dockerfile文件募舟,進(jìn)行鏡像制作,使用docker build命令進(jìn)行鏡像的構(gòu)建闻察。第一種方式可以看到鏡像的生成過程拱礁,但是不便于自動(dòng)化;第二種方式則比較直觀蜓陌,可以結(jié)合devops實(shí)現(xiàn)自動(dòng)打包發(fā)布觅彰,本文則介紹如何利用dockerfile實(shí)現(xiàn)docker鏡像的制作。
Dockerfile描述了組裝鏡像的步驟钮热,其中每條指令都是單獨(dú)執(zhí)行的填抬。除了FROM指令之外,其他每一條指令都會(huì)在上一條指令生成的鏡像上執(zhí)行并生成一個(gè)新的鏡像層隧期。Dockerfile生成的最終鏡像就是在基礎(chǔ)鏡像上一層一層疊加組建而成的飒责。同時(shí)赘娄,為了提高鏡像構(gòu)建的速度,Docker會(huì)緩存構(gòu)建過程中的中間鏡像宏蛉。當(dāng)從一個(gè)已在緩存中的基礎(chǔ)鏡像開始構(gòu)建新鏡像時(shí)遣臼,會(huì)將dockerfile中的下一條指令和基礎(chǔ)鏡像的所有子鏡像做比較,如果有一個(gè)子鏡像是由相同的指令生成的拾并,則命中緩存揍堰,直接使用該鏡像。這里我們需要注意一點(diǎn)嗅义,鏡像制作過程中緩存命中與否檢查的是dockerfile中的指令屏歹,并不會(huì)檢查鏡像是否一致;當(dāng)然COPY,ADD兩個(gè)指令例外之碗,不僅檢測會(huì)指令字符集蝙眶,還會(huì)檢測對(duì)比需要添加的文件是否一致(校驗(yàn)不考慮修改訪問時(shí)間,考慮元數(shù)據(jù)以及內(nèi)容)褪那。如我們在鏡像中使用了
RUN apt-get -y upgrade
指令幽纷,docker daemon在校驗(yàn)的時(shí)候,會(huì)判斷指令集相同博敬,從而使用緩存并不會(huì)更新友浸。解決這個(gè)問題可以使用下列方法,人為的造成指令字符集不一致
RUN apt-get update && apt-get install -y \
aufs-tools \
automake \
build-essential \
&& rm -rf /var/lib/apt/lists/*
另外一種方法就是在docker build時(shí)添加參數(shù) --no-cache=true
二偏窝,典型結(jié)構(gòu)
#第一部分 指明基礎(chǔ)鏡像
#FROM registry:5000/centos_ssh:1.0.0
FROM registry:5000/centos:7.3.1611
##第二部分 維護(hù)者信息
MAINTAINER liyang liyang@pand-auto.com
## 第三部分 鏡像操作指令
#更改時(shí)區(qū)
RUN echo "Asia/Shanghai" > /etc/timezone
# 設(shè)置環(huán)境變量
#ENV CATALINA_HOME /usr/local/tomcat
ENV JAVA_HOME /usr/local/jdk1.8.0_161
ENV PATH $PATH:$JAVA_HOME/bin
#ENV PATH $PATH:$CATALINA_HOME/bin
#創(chuàng)建日志目錄
RUN mkdir -p /www/logs/applogs
#拷貝host文件至容器中尾菇,以便后續(xù)直接添加至容器host文件中
COPY hosts /myhosts
#拷貝tomcat和jdk文件到容器中
COPY tomcat /usr/local/
COPY jdk1.8.0_161 /usr/local/jdk1.8.0_161
#拷貝啟動(dòng)腳本至容器中
COPY run.sh /run.sh
RUN chmod +x /run.sh
#拷貝后臺(tái)項(xiàng)目至容器中
COPY VRBP_Admin_war_exploded /tomcat/webapps/Admin
EXPOSE 8080
## 第四部分 容器啟動(dòng)時(shí)執(zhí)行的命令
CMD [ "/run.sh" ]
run.sh內(nèi)容如下:
#!/bin/bash
cat /myhosts >>/etc/hosts
${CATALINA_HOME}/bin/catalina.sh run
注:因?yàn)槊看螁?dòng)容器的時(shí)候hosts文件都會(huì)重新生成,所以本文中鏡像采用啟動(dòng)后執(zhí)行命令將hosts內(nèi)容追加至/etc/hosts文件中的方法
三囚枪,常用指令說明
FROM
格式: FROM <image> 或者 FROM <image>:<tag>
FROM指令的功能是為后面的指令提供基礎(chǔ)鏡像派诬,所以該指令一定是Dockerfile的第一個(gè)非注釋指令。如果FROM指令中沒有指明tag链沼,則默認(rèn)為latest
MAINTAINER
格式:MAINTAINER <information of maintaier>
MAINTAINER指明鏡像維護(hù)者的信息默赂,通常是dockerfile的第二個(gè)非注釋指令
ENV
格式:ENV <key> <value> 或者 ENV <key>=<value> ...
ENV指令為鏡像創(chuàng)建出來的容器聲明環(huán)境變量,并且可以在dockerfile被特定指令使用(ADD,COPY,EXPOSE,WORKDIR等)
需要注意一點(diǎn)的是括勺,定義容器中的變量的時(shí)候盡量不要使用/etc/profile文件缆八,直接使用ENV定義。因?yàn)樵撆渲梦募挥性诮换ナ絾?dòng)shell時(shí)候才會(huì)讀取疾捍,而docker run使
用的是/bin/bash -c奈辰,非交互式模式,所以直接寫入/etc/profile的環(huán)境變量不能直接生效乱豆,需要source一遍配置文件奖恰,推薦使用ENV直接定義固化。
RUN
格式:RUN <command> 或者 RUN ["executable","param1","param2"]
RUN指令會(huì)在前一條命令創(chuàng)建的鏡像基礎(chǔ)上創(chuàng)建一個(gè)容器,并在容器中運(yùn)行命令瑟啃,在命令結(jié)束運(yùn)行后提交容器為新的鏡像
RUN指令兩種運(yùn)行方式可以理解為shell以及exec格式论泛,當(dāng)使用shell格式時(shí),命令通過調(diào)用/bin/sh -c運(yùn)行蛹屿;使用exec格式時(shí)屁奏,命令直接運(yùn)行,容易不調(diào)用shell错负,exec格式
格式中的參數(shù)會(huì)被當(dāng)做JSON被docker解析坟瓢,exec不會(huì)在shell中執(zhí)行,所以環(huán)境變量的參數(shù)不會(huì)被替換犹撒。
COPY/ADD
格式:ADD/COPY <src> <dest>
COPY载绿,ADD指令都可以拷貝本地文件或者目錄到新的鏡像中,其中ADD命令還支持URL并且可以在自動(dòng)解壓tar包油航。如果原路徑是一個(gè)目錄,則只會(huì)拷貝目錄中的內(nèi)容怀浆,不
會(huì)在鏡像中創(chuàng)建該目錄谊囚;源路徑是相對(duì)于執(zhí)行build的相對(duì)路徑;目標(biāo)路徑不存在時(shí)會(huì)自動(dòng)創(chuàng)建执赡;
CMD
格式:有下列三種
CMD <command>
CMD ["executable","Param1","param2"]
CMD ["Param1","param2"] 為ENTRYPOINT傳遞參數(shù)
CMD指令提供容器啟動(dòng)時(shí)運(yùn)行的默認(rèn)值镰踏,可以為參數(shù),命令沙合。當(dāng)一個(gè)dockerfile文件中存在多個(gè)CMD指令時(shí)奠伪,只有最后一個(gè)CMD生效。CMD指令在鏡像構(gòu)建時(shí)不運(yùn)行任何命
令首懈,而是在容器啟動(dòng)時(shí)默認(rèn)將CMD指令作為第一條執(zhí)行的命令绊率,如果用戶在docker run命令中指定了命令參數(shù)則會(huì)覆蓋CMD指令中的命令
ENTRYPOINT
格式:
ENTRYPOINT <command>
ENTRYPOINT ["executable","Param1","param2"]
ENTRYPOINT指令與CMD指令類似,不同點(diǎn)在于ENTRYPOINT不會(huì)被docker run中的命令參數(shù)覆蓋
EXPOSE
格式:EXPOSE [...]
定義容器向外暴露的窗口究履,不建議在此處定義端口映射
四滤否,鏡像構(gòu)建
命令:docker build -t <image>:<tag> .
上述命令中最后有一個(gè)點(diǎn),表示dockerfile所在的目錄最仑,也可以直接寫為絕對(duì)路徑(不推薦)藐俺,該命令會(huì)自動(dòng)去尋找目錄下的Dockerfile文件并讀取其內(nèi)容。也可以使用 -f指明dockerfile文件路徑泥彤。
注意:
1.固定內(nèi)容盡量寫在dockerfile前列欲芹,充分利用緩存
2.RUN指令的命令結(jié)合管道可以減少鏡像層數(shù)
3.CMD和ENTRYPOINT可以結(jié)合使用
4.如果是本地文件盡量使用COPY