docker学习笔记八、Dockerfile实战教程

docker学习笔记八、Dockerfile实战教程

2023年7月6日发(作者:)

docker学习笔记⼋、Dockerfile实战教程⼀、初识1、Docker 简介:镜像的定制实际上就是定制每⼀层所添加的配置、⽂件。那么如果我们可以把每⼀层修改、安装、构建、操作的命令都写⼊⼀个脚本,⽤这个脚本来构建、定制镜像,那么之前提及的⽆法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是Dockerfile。Dockerfile描述了组装镜像的步骤,其中每⼀条命令都是单独执⾏的,除了FROM指令外,其他每⼀条指令都在上⼀条指定所⽣成的镜像基础上执⾏,执⾏完会⽣成⼀个新的镜像层,新的镜像层覆盖在原来的镜像层之上,从⽽形成了新的镜像。Dockerfile所⽣成的最终镜像就是在基础叠加镜像上⼀层层的镜像层组成的。在Dockerfile中,指令不区分⼤⼩写,但是为了与参数区分,推荐⼤写。Docker会顺序执⾏Dockerfile中的指令,第⼀条必须是FROM指令,它⽤于指定构建镜像的基础镜像。在Dockerfile中,以#开头的⾏是注释。

2、FROM指令和RUN指令FROM指定基础镜像;格式:FROM 或 FROM :。FROM指令的功能是为后⾯的指令提供基础镜像,因此⼀个有效的Dockerfile必须以FROM指令作为第⼀条⾮注解指令。若FROM指令中tag参数为空,则tag默认为latest;若参数image或tag指定镜像不存在,则返回错误。RUN执⾏命令;格式:RUN (shell格式)或RUN [“executable”, “param1“, “param2”](exec格式,⾮常推荐)。RUN指令是⽤来执⾏命令⾏命令的。RUN指令会在前⼀条命令创建出的镜像的基础上创建⼀个容器,并在容器中运⾏命令。在命令结束运⾏后提交新容器为新镜像,新镜像被Dockerfile的下⼀条指令使⽤

3、Dockerfile构建⼀个镜像步骤:⾸先创建⼀个空⽂件夹:mkdir newdir;然后进⼊该⽂件夹:cd newdir;在该⽂件夹下创建⼀个名为Dockerfile的⽂件,根据实际需求补全Dockerfile的内容;使⽤Dockerfile构建⼀个镜像:docker build -t testimage .(注意这个⼩数点)其中-t指定新镜像的镜像名。构建第⼆次参考案例2

例⼦1:#先创建⼀个新的空⽂件夹#mkdir newdir#进⼊这个新⽂件夹中#cd newdir#创建⼀个Dockerfile⽂件#touch Dockerfile#补全Dockerfile的内容(为了⽅便展⽰,这⾥⽤的是echo向Dockerfile中输⼊内容)#echo "FROM ubuntu:latest" > Dockerfile#echo "RUN mkdir /dir1" >> Dockerfile#使⽤该Dockerfile构建⼀个名为testimage的镜像#docker build -t testimage . //这个点注意有空格Dockerfile 的内容为下FROM ubuntu:latestRUN mkdir /dir1

Docker指令是从上到下⼀层⼀层执⾏的,所以在使⽤这个Dockerfile构建镜像时,⾸先执⾏FROM ubuntu:latest这条指令。FROM ubuntu:latest指定ubuntu:latest作为基础镜像,也就是将ubuntu:latest镜像的所有镜像层放置在testimage镜像的最下⾯。然后执⾏RUN mkdir dir1指令,前⾯我们说过,执⾏RUN指令时,会在之前指令创建出的镜像的基础上创建⼀个临时容器,在这⾥的容器Id为c5117d908931,并在容器中运⾏命令。在命令结束运⾏后提交新容器为新镜像,并删除临时创建的容器c5117d908931。在Dockerfile的所有指令执⾏完后,新镜像就构建完成了!

注意事项,谨慎使⽤RUN4、修改前的Dokcerfile⽂件

修改Dockerfile 构建第⼆层镜像FROM debian:jessieRUN buildDeps='gcc libc6-dev make' && apt-get update && apt-get install -y $buildDeps && wget -O "/releases/" && mkdir -p /usr/src/redis && tar -xzf -C /usr/src/redis --strip-components=1 && make -C /usr/src/redis && make -C /usr/src/redis install && rm -rf /var/lib/apt/lists/* && rm && rm -r /usr/src/redis && apt-get purge -y --auto-remove $buildDeps

在Dockerfile的编写过程中⼀定要牢记⼀点:镜像的每⼀层构建完就不会再发⽣改变,后⼀层上的任何改变只发⽣在⾃⼰这⼀层。删除前⼀层⽂件的操作,实际不是真的删除前⼀层的⽂件,⽽是仅在当前层标记为该⽂件已删除。在最终容器运⾏的时候,虽然不会看到这个⽂件,但是实际上该⽂件会⼀直跟随镜像。

例⼦2#创建⼀个空⽂件夹,并进⼊其中mkdir newdir1cd newdir1#创建⼀个Dockerfile⽂件touch Dockerfile#假设我的Dockerfile⽂件为#FROM ubuntu#RUN mkdir dir1#可以这么写:# echo 'FROM ubuntu' > Dockerfile# echo 'RUN mkdir dir1'>> Dockerfile#输⼊Dockerfile⽂件内容#********** Begin *********##以busybox为基础镜像echo 'FROM busybox'> Dockerfile#在基础镜像的基础上,创建⼀个⽂件echo 'RUN touch '>> Dockerfile#********** End **********##使⽤Dockerfile创建⼀个新镜像,镜像名为busybox:v1docker build -t busybox:v1 . //注意这个点 有空格⼆、docker build、COPY和ADD1、docker buid 命令详解Dockerfile创建完成后,可以使⽤docker build命令根据Dockerfile构建⼀个镜像。在上⼀关中,我们在Dockerfile所在的⽂件夹下执⾏docker build -t myimage .这条命令,然后镜像就被构建了

#docker build [OPTIONS] 上下⽂路径|URLdocker build: ⽤Dockerfile构建镜像的命令关键词;[OPTIONS]: 命令选项,常⽤的指令包括-t指定镜像的名字,-f显⽰指定Dockerfile,如果不使⽤-f,则默认将上下⽂路径下的名为Dockerfile的⽂件认为是构建镜像的“Dockerfile”;上下⽂路径|URL: 指定构建镜像的上下⽂的路径,构建镜像的过程中,可以且只可以引⽤上下⽂中的任何⽂件

2、COPY指令和ADD指令 1)COPY复制⽂件;格式:COPY <源路径> <⽬标路径>;COPY 指令将从构建上下⽂⽬录中 <源路径> 的⽂件或⽬录复制到新的⼀层的镜像内的 <⽬标路径> 位置。<源路径>所指定的源必须在上下⽂中,即必须是上下⽂根⽬录的相对路径!<⽬标路径> 可以是容器内的绝对路径,也可以是相对于⼯作⽬录的相对路径(⼯作⽬录可以⽤WORKDIR指令来指定,后⾯介绍)。⽬标路径不需要事先创建,如果⽬录不存在会在复制⽂件前先⾏创建⽬录。2)ADD更⾼级的⽂件复制;格式:ADD <源路径> <⽬标路径>;ADD与COPY指令在功能上⼗分相似,但是在COPY的基础上增加了⼀些功能。⽐如,源路径可以是⼀个指向⼀个⽹络⽂件的URL,这种情况下,Docker引擎会试图下载这个URL指向的⽂件到<⽬标路径>去。此外,当<源路径>为⼀个tar压缩⽂件时,该压缩⽂件在被复制到容器中时会被解压提取。但是使⽤COPY指令只会将tar压缩⽂件拷贝到<⽬标路径>中

例⼦:#创建⼀个空⽂件夹,并进⼊其中mkdir newdir2cd newdir2#创建⼀个⽂件夹dir1,将其压缩,然后删除dir1mkdir dir1 && tar -cvf dir1 && rmdir dir1#创建⼀个Dockerfile⽂件touch Dockerfile#假设我的Dockerfile⽂件为#FROM ubuntu#RUN mkdir dir1#可以这么写:# echo 'FROM ubuntu' > Dockerfile# echo 'RUN mkdir dir1'>> Dockerfile#输⼊Dockerfile⽂件内容#********** Begin *********##以busybox为基础镜像echo 'FROM busybox'> Dockerfile#并将上下⽂⽬录下的“解压提取后”,拷贝到busybox:v3的/echo 'ADD /'>> Dockerfile#********** End **********##⽂件内容完毕,在当前⽂件夹中执⾏#********** Begin *********##以该Dockerfile构建⼀个名为busybox:v3的镜像docker build -t busybox:v3 .#********** End **********#

三、CMD和ENTRYPOINT指令1、CMD指令CMD 指定默认的容器主进程启动命令格式:CMD (shell格式)或 CMD [“executable”,”param1”,”param2”](exec格式,推荐格式)或CMD[”param1”,”param2”]。(为ENTRYPOINT指令提供参数) CMD指令提供容器启动时运⾏的默认命令,例如ubuntu镜像默认的CMD是/bin/bash,因此我们可以直接使⽤ docker run -it ubuntu进⼊bash。同时也可以使⽤docker run -it ubuntu cat /etc/os-release,执⾏该命令后会输出系统版本信息。因为当在执⾏docker run命令时,如果显⽰地指定了容器的启动命令,那么会将Dockerfile中CMD设置的默认启动命令覆盖,也就是说:cat /etc/os-release命令会替代成为容器的启动命令,所以输出了系统版本信息。在指令格式上,⼀般推荐使⽤exec格式,因为使⽤ shell格式时,实际的命令会被包装为 sh -c的参数的形式进⾏执⾏。⽐如:CMD echo$HOME,在实际执⾏中,会将其变更为:CMD [ "sh", "-c", "echo $HOME" ]。

2、ENTRYPOINT指令ENTRYPOINT 指定默认的容器主进程启动命令格式:ENTRYPOINT (shell格式)或ENTRYPOINT [“executable”,”param1”,”param2”]。(exec格式,推荐格式)ENTRYPOINT和CMD⼀样,都可以指定容器默认的启动命令,但是它⼜和CMD有所不同。上⾯我们说过,⽤户在执⾏docker run命令创建并启动容器时,如果指定了启动命令,那么“该启动命令”会覆盖CMD指令设置的默认启动命令,但是ENTRYPOINT设置的启动命令该不能被覆盖。细⼼的同学可能发现了CMD命令可以为ENTRYPOINT指令提供参数。实际上,如果使⽤Dockerfile构建镜像时,既使⽤了ENTRYPOINT指令,⼜指定了CMD指令,那么CMD指令的含义就发⽣了改变, CMD 的内容将作为参数传给 ENTRYPOINT指令,换句话说实际执⾏时,变成了 。同时,如果执⾏docker run基于该镜像创建并启动容器,并设置了启动命令时,docker run设置的“启动命令”依然会覆盖CMD的内容,但也仅仅是作为ENTRYPOINT指令的参数。

例⼦ #创建⼀个空⽂件夹,并进⼊其中mkdir newdir3cd newdir3#创建⼀个Dockerfile⽂件touch Dockerfile#假设我的Dockerfile⽂件为#FROM ubuntu#RUN mkdir dir1#可以这么写:# echo 'FROM ubuntu' > Dockerfile# echo 'RUN mkdir dir1'>> Dockerfile#输⼊Dockerfile⽂件内容#********** Begin *********##以busybox为基础镜像echo 'FROM busybox'>Dockerfile#默认情况下,将启动命令设置为df -Th。要求df命令不能被覆盖,但-Th能够被覆盖。echo 'ENTRYPOINT ["df"]'>>Dockerfileecho 'CMD ["-Th"]'>>Dockerfile#********** End **********##⽂件内容完毕,在当前⽂件夹中执⾏#********** Begin *********##以该Dockerfile构建⼀个名为mydisk:latest的镜像docker build -t mydisk .#********** End **********#四、ENV、EXPOSE、WORKDIR、ARG

1、WORKDIR指令WORKDIR为其他指令设置⼯作⽬录;格式:WORKDIR <⼯作⽬录路径>;WORKDIR指令为Dockerfile中的任何RUN,CMD,ENTRYPOINT,COPY和ADD指令设置⼯作⽬录(或称当前⽬录)。(也就是说以后各层的当前⽬录就被改为WORKDIR指定的⽬录)如果WORKDIR对应的⽬录不存在,将会⾃动被创建。

2、ENV指令ENV设置环境变量;格式:ENV 或ENV =;这个指令很简单,就是设置环境变量⽽已,⽆论是后⾯的其它指令,还是运⾏时的应⽤,都可以直接使⽤这⾥定义的环境变量。如下所⽰,下⾯是为tomcat设置环境变量并让tomcat⾃启动的⼀个Dockerfile⽚段。ENV设置的环境变量CATALINA_HOME能够被后续定义指令使⽤。ENV CATALINA_HOME /var/tmp/apache-tomcat-8.0.45ENV PATH $PATH: $CATALINA_HOME/binENTRYPOINT $CATALINA_HOME /bin/ && /bin/bash

3、ARG指令ARG构建参数;格式:ARG <参数名>[=<默认值>];ARG与ENV有些类似,它们都可以被后⾯的其它指令直接使⽤,但是它并不是环境变量,这意味着将来容器运⾏时是不会存在ARG变量的。Dockerfile中的ARG指令是定义参数名称,以及定义其默认值。该默认值可以在构建命令docker build 中⽤ --build-arg <参数名>=<值>来覆盖。什么时候⽤ARG,什么时候⽤ENV?如果想保存为环境变量,就⽤ENV;如果只想在Dockerfile中临时使⽤,就⽤ARG。

4、EXPOSE指令EXPOSE暴露端⼝;格式:EXPOSE <端⼝1> [<端⼝2>...]

例⼦1使⽤ENV配置java与tomcat的环境变量,由于tomcat服务会默认监听8080端⼝,所以使⽤EXPOSE暴露端⼝号。最后使⽤ENTRYPOINT设置启动命令,使tomcat服务随容器启动⽽启动例⼦1:FROM ubuntuWORKDIR /var/tmpRUN apt-get update && apt-get install -y wget && wget --no-check-certificate --no-cookies --header "Cookie: ofraclelicense=accept-securebackup-cookie" /otn-pub/java/jdk/8u144-b01tar -xzf && rm wget "/apache/tomcat/tomcat-8/v8.0.45/bin/" && tar -xzf && rm JAVA_HOME /var/tmp/jre1.8.0_144ENV CATALINA_HOME /var/tmp/apache-tomcat-8.0.45ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/binEXPOSE 8080ENTRYPOINT /var/tmp/apache-tomcat-8.0.45/bin/ && /bin/bash

例⼦2#创建⼀个空⽂件夹,并进⼊其中mkdir newdir4cd newdir4#创建⼀个Dockerfile⽂件touch Dockerfile#假设我的Dockerfile⽂件为#FROM ubuntu#RUN mkdir dir1#可以这么写:# echo 'FROM ubuntu' > Dockerfile# echo 'RUN mkdir dir1'>> Dockerfile#输⼊Dockerfile⽂件内容#********** Begin *********##以busybox为基础镜像echo 'FROM busybox' > Dockerfile#声明暴露3000端⼝echo 'EXPOSE 3000' >> Dockerfile#将变量var1=test设置为环境变量echo 'ENV var1=test' >> Dockerfile#设置⼯作⽬录为/tmpecho 'WORKDIR /tmp' >> Dockerfile#在⼯作⽬录下创建⼀个⽂件echo 'RUN touch ' >> Dockerfile#********** End **********##⽂件内容完毕,在当前⽂件夹中执⾏#********** Begin *********##以该Dockerfile构建⼀个名为testimage:v1的镜像docker build -t testimage:v1 .#********** End **********#

发布者:admin,转转请注明出处:http://www.yc00.com/web/1688592141a153119.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信