一、簡(jiǎn)介
1.是什么
Dockerfile是用來(lái)構(gòu)建Docker鏡像的構(gòu)建文件,是由一系列命令和參數(shù)構(gòu)成的腳步
構(gòu)建三步驟:
- 編寫Dockerfile文件
- docker build
- docker run
2.Dockerfile構(gòu)建過(guò)程解析
2.1 內(nèi)容基礎(chǔ)知識(shí)
- 每條保留字命令都必須為大寫字母且后面要跟隨至少一個(gè)參數(shù)
- 指令按照從上到下,順序執(zhí)行
- #表示注釋
- 每條指令都會(huì)創(chuàng)建一個(gè)新的鏡像層,并對(duì)鏡像進(jìn)行提交
2.2 執(zhí)行Dockerfile的大致流程
- docker從基礎(chǔ)鏡像運(yùn)行一個(gè)容器
- 執(zhí)行一條指令并對(duì)容器作出修改
- 執(zhí)行類似docker commit的操作提交一個(gè)新的鏡像
- docker再基于剛提交的鏡像運(yùn)行一個(gè)新容器
- 執(zhí)行dockerfile中的下一條指令直到所有指令都執(zhí)行完畢
從應(yīng)用軟件的角度來(lái)看,Dockerfile、Docker鏡像與Docker容器分別代表軟件的三個(gè)不同階段,
- Dockerfile是軟件的原材料
- Docker鏡像是軟件的交付品
- Docker容器則可以認(rèn)為是軟件的運(yùn)行態(tài)。
Dockerfile面向開(kāi)發(fā),Docker鏡像成為交付標(biāo)準(zhǔn),Docker容器則涉及部署與運(yùn)維,三者缺一不可,合力充當(dāng)Docker體系的基石。
二、保留字指令
FROM:基礎(chǔ)鏡像,當(dāng)前新鏡像是基于哪個(gè)鏡像的,指定一個(gè)已經(jīng)存在的鏡像作為模板,第一條必須是FROM
MAINTAINER:鏡像維護(hù)者的姓名和郵箱地址
-
RUN:容器創(chuàng)建時(shí)需要運(yùn)行的命令
-
兩種格式:
-
shell格式:
RUN <命令行命令> 等同于在終端操作的 shell 命令
RUN yum -y install vim EXEC格式:RUN ["可執(zhí)行文件", "參數(shù)1", "參數(shù)2"]
RUN ["./test.php", "dev", "offline"] 等價(jià)于 RUN ./test.php dev offline
-
RUN 在docker build 時(shí)運(yùn)行
-
EXPOSE:當(dāng)前容器對(duì)外暴露出的端口
WORKDIR:指定在創(chuàng)建容器后,終端默認(rèn)登錄的進(jìn)來(lái)工作目錄,一個(gè)落腳點(diǎn)
USER:指定該鏡像以什么樣的用戶去執(zhí)行,如果都不指定,默認(rèn)是root
-
ENV:用來(lái)構(gòu)建鏡像過(guò)程中設(shè)置環(huán)境變量
ENV MY_PATH /usr/mytest這個(gè)環(huán)境變量可以在后續(xù)的任何RUN指令中使用,這就如同在命令前面指定了環(huán)境變量前綴一樣;也可以在其它指令中直接使用這些環(huán)境變量,比如:WORKDIR $MY_PATH ADD:將宿主機(jī)目錄下的文件拷貝進(jìn)鏡像且ADD命令會(huì)自動(dòng)出來(lái)URL和解壓tar壓縮包
-
COPY:類似ADD,拷貝文件和目錄到鏡像中。將從構(gòu)建上下文目錄中<源路徑>的文件/目錄復(fù)制到新的一層的鏡像內(nèi)的<目標(biāo)路徑>位置,不同ADD,此命令不會(huì)解壓壓縮包
COPY src destCOPY ["src","dest"]
<src源路徑>:源文件或源目錄,<dest目標(biāo)路徑>:容器內(nèi)指定路徑,路徑不存在會(huì)自動(dòng)創(chuàng)建
VOLUME:容器數(shù)據(jù)卷,用于數(shù)據(jù)保存和持久化工作
-
CMD:指定一個(gè)容器啟動(dòng)時(shí)要干的事情,Dockerfile中可以有多個(gè)CMD指令,但只有最后一個(gè)生效,CMD會(huì)被docker run之后的參數(shù)替換
參考官網(wǎng)Tomcat 的 dockerfile ,官網(wǎng)最后一行命令
EXPOSE 8080 CMD ["catalina.sh", "run"]自己覆蓋操作:
docker run -it -p 8080:8080 容器id /bin/bash,/bin/bash 會(huì)覆蓋掉 CMD 后面的參數(shù)CMD 是在docker run時(shí)運(yùn)行
RUN 是在docker build 時(shí)運(yùn)行
-
ENTRYPOINT:指定一個(gè)容器啟動(dòng)時(shí)要運(yùn)行的命令,ENTRYPOINT的目的和CMD一樣,都是在指定容器啟動(dòng)程序和參數(shù),但是ENTRYPOINT不會(huì)被docker run后面的命令覆蓋,而且這些命令行參數(shù)會(huì)被當(dāng)做參數(shù)送給ENTRYPOINT 指令指定的程序
命令格式:
ENTRYPOINT ["<executeable>", "<param1>", "<param2>", ...]案例:假設(shè)已通過(guò) Dockerfile 構(gòu)建了 nginx:test 鏡像:
FROM nginx ENTRYPOINT ["nginx", "-c"] #定參 CMD ["/etc/nginx/nginx.conf"] #變參當(dāng)指定了ENTRYPOINT后,CMD的含義就發(fā)生了變化,不再是直接運(yùn)行其命令而是將CMD的內(nèi)容作為參數(shù)傳遞給ENTRYPOINT指令,他兩個(gè)組合會(huì)變成:ENTRYPOINT CMD
-
docker run nginx:test實(shí)際命令:nginx -c /etc/nginx/nginx.conf -
docker run nginx:test -c /etc/nginx/new.conf實(shí)際命令:nginx -c /etc/nginx/new.conf
在執(zhí)行 docker run 的時(shí)候可以指定 ENTRYPOINT 運(yùn)行所需的參數(shù)
如果 Dockerfile 中如果存在多個(gè) ENTRYPOINT 指令,僅最后一個(gè)生效
-
ONBUILD:當(dāng)構(gòu)建一個(gè)被繼承的Dockerfile時(shí)運(yùn)行命令,父鏡像在被子繼承后父鏡像的onbuild被處罰
三、保留字字段案例
1.Base鏡像(scratch)
Docker Hub中99%的鏡像都是通過(guò)base鏡像中安裝和配置需要的軟件構(gòu)建出來(lái)的
FROM scratch
2.自定義鏡像
-
編寫Dockerfile文件
FROM centos MAINTAINER xx<xx@qq.com> ENV MYPATH /usr/local WORKDIR $MYPATH RUN yum -y install vim RUN yum -y install net-tools EXPOSE 80 CMD echo $MYPATH CMD echo "success--------------ok" CMD /bin/bash 構(gòu)建
docker build -t 新鏡像名字:TAG .運(yùn)行
docker run -it 新鏡像名字:TAG列出鏡像的變更歷史
docker history 鏡像名
3.CMD和ENTRYPOINT
CMD
指定一個(gè)容器啟動(dòng)時(shí)要運(yùn)行的命令(Dockerfile中可以有多個(gè)CMD指令,但只有最后一個(gè)生效,CMD會(huì)被docker run之后的參數(shù)替換)
在tomcat的dockerfile中,執(zhí)行cmd語(yǔ)句啟動(dòng)tomcat
tomcat:
EXPOSE 8080
CMD ["catalina.sh","run"]
$ docker run -it -p 8080:8080 tomcat
容器啟動(dòng)能訪問(wèn)8080
$ docker run -it -p 7777:8080 tomcat ls -l
相當(dāng)于在dockerfile末尾添加CMD ls -l, CMD會(huì)被docker run后參數(shù)替換,tomcat就不會(huì)啟動(dòng)
ENTRYPOINT
docker run之后參數(shù)會(huì)被當(dāng)做參數(shù)傳遞給ENTRYPOINT(追加),之后會(huì)形成新的命令組合
curl www.baidu.com 抓取百度的html
抓取ip:curl -s http://ip.cn,想實(shí)現(xiàn)顯示http頭信息需要:curl -s -i http://ip.cn
FROM centos
RUN yum install -y curl
CMD ["curl',"-s","http://ip.cn"]
文件構(gòu)建成myip鏡像,需要輸出head內(nèi)容
$ docker run myip curl -s http://ip.cn -i
用ENTRYPOINT,修改dockerfile
FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl',"-s","http://ip.cn"]
執(zhí)行
$ docker build -f /mydocker/dockerfile -t myip .
$ docker run myip -i
# 相當(dāng)于啟動(dòng)容器后執(zhí)行下面命令,追加 -i
$ curl -s http://ip.cn -i
4.ONBUILD
myip鏡像
FROM centos
RUN yum install -y curl
ENTRYPOINT ["curl',"-s","http://ip.cn"]
ONBUILD RUN echo "父類運(yùn)行"
myip2鏡像
FROM myip
RUN yum install -y curl
ENTRYPOINT ["curl',"-s","http://ip.cn"]
當(dāng)執(zhí)行myip2鏡像時(shí)候,會(huì)出現(xiàn)myip中ONBUILD定義的
5.完整實(shí)例
FROM centos
MAINTAINER zy<zy@163.com>
#把宿主機(jī)當(dāng)前上下文c.txt拷貝到容器/usr/local路徑下,加上mm.txt,重命名為mm.txt
COPY c.txt /usr/local/mm.txt
#把jdk解壓添加到容器中
ADD JDK-8u171.tar.gz /usr/local/
ADD tomcat.tar.gz /usr/local/
#安裝vim編輯器
RUN yum -y install vim
#設(shè)置工作訪問(wèn)時(shí)候的路徑,登錄落腳點(diǎn)
ENV MYPATH /usr/local
WORKDIR $MYPATH
#配置java,tomcat環(huán)境變量
ENV JAVA_HOME /usr/local/jdk1.8.0_171
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.8
ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_BASE/bin
#容器運(yùn)行時(shí)候監(jiān)聽(tīng)端口
EXPORT 8080
#啟動(dòng)時(shí)候運(yùn)行tomcat,下面都可以
# ENTRYPOINT ["/usr/local/apache-tomcat-x.x.x/bin/startup.sh"]
# CMD ["/usr/local/apache-tomcat-x.x.x/bin/startup.sh","run"]
CMD /usr/local/apache-tomcat-x.x.x/bin/startup.sh && tail -F /usr/local/apache-tomcat-x.x.x/bin/logs/catalina.out
在當(dāng)前文件下如果存在文件Dockerfile,可以不用-f Dockerfile
$ docker build -t zytomcat .
$ docker run -d -p 8090:8080 --name myTomcat
-v /user/mydockerfile/tomcat/test:/usr/local/apache-tomcat-9.0.8/webapps/test
-v /user/mydockerfile/tomcat/logs:/usr/local/apache-tomcat-9.0.8/logs
--privileged=true //權(quán)限不足使用
tomcat
四、虛懸鏡像
倉(cāng)庫(kù)名、標(biāo)簽都是 <none> 的鏡像,俗稱 dangling image
創(chuàng)建
Dockerfile寫一個(gè)
1.vim Dockerfile
FROM ubuntu
CMD echo 'action is sucess'
2.docker build .
查看
docker image ls -f dangling=true
刪除
docker image prune