Dockerfile詳解

一、簡(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 dest
    • COPY ["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.自定義鏡像

  1. 編寫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 
    
  2. 構(gòu)建
    docker build -t 新鏡像名字:TAG .

  3. 運(yùn)行
    docker run -it 新鏡像名字:TAG

  4. 列出鏡像的變更歷史
    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
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容