什么是Dockerfile
这篇文章主要介绍"什么是Dockerfile",在日常操作中,相信很多人在什么是Dockerfile问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"什么是Dockerfile"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
一 DockerFile构建过程解析
1.Dockerfile内容基础知识
每条保留字指令都必须为大写字母且后面要跟随至少一个参数
指令按照从上到下,顺序执行
#表示注释
每条指令都会创建一个新的镜像层,并对镜像进行提交
2 Docker执行Dockerfile的大致流程
docker从基础镜像运行一个容器
执行一条指令并对容器作出修改
执行类似docker commit的操作提交一个新的镜像层
docker再基于刚提交的镜像运行一个新容器
执行dockerfile中的下一条指令直到所有指令都执行完成
3 小总结
从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,
Dockerfile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件的运行态。 Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石
Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
Docker容器,容器是直接提供服务的。
二 DockerFile体系结构(保留字指令)
FROM
基础镜像,当前新镜像是基于哪个镜像的
MAINTAINER
镜像维护者的姓名和邮箱地址
RUN
容器构建时需要运行的命令
EXPOSE
当前容器对外暴露出的端口
WORKDIR
指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
ENV
用来在构建镜像过程中设置环境变量
例如:ENV MY_PATH /usr/mytest 这个环境变量可以在后续的任何RUN指令中使用,这就如同在命令前面指定了环境变量前缀一样;也可以在其它指令中直接使用这些环境变量, 比如:WORKDIR $MY_PATH
ADD
将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
COPY
类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置
VOLUME
容器数据卷,用于数据保存和持久化工作
CMD
指定一个容器启动时要运行的命令
三 案例
Base镜像(scratch)
Docker Hub 中 99% 的镜像都是通过在 base 镜像中安装和配置需要的软件构建出来的
自定义镜像 mycentos
1 编写
Hub默认CentOS镜像的情况
myCentOS内容Dockerfile
FROM centosMAINTAINER zhl<253316343@qq.com>ENV MYPATH /usr/localWORKDIR $MYPATHRUN yum -y install vimRUN yum -y install net-toolsEXPOSE 80CMD echo $MYPATHCMD echo "success ------ ok"CMD /bin/bash
2 构建
docker build -f DockerFile目录 -t 新镜像名字:TAG . . 表示当前目录
docker build -f /opt/docker/mydocker/Dockerfile -t zhl/centos1.1 .
root@zhanghl:/opt/docker/mydocker# docker build -f /opt/docker/mydocker/Dockerfile -t zhl/centos1.1 .Sending build context to Docker daemon 2.048kBStep 1/10 : FROM centos ---> 300e315adb2fStep 2/10 : MAINTAINER zhl<253316343@qq.com> ---> Running in 9cef0b83aa4dRemoving intermediate container 9cef0b83aa4d ---> e03c70aa84ddStep 3/10 : ENV MYPATH /usr/local ---> Running in a06eb1e589daRemoving intermediate container a06eb1e589da ---> f817774de33bStep 4/10 : WORKDIR $MYPATH ---> Running in 2638200252e1Removing intermediate container 2638200252e1 ---> e0ac249d8189Step 5/10 : RUN yum -y install vim ---> Running in 23a14562d0d6....... ---> 059822073508Step 6/10 : RUN yum -y install net-tools ---> Running in 4a437d96a483..... ---> c49737740d20Step 7/10 : EXPOSE 80 ---> Running in 326caf878a8eRemoving intermediate container 326caf878a8e ---> 6690abcca60fStep 8/10 : CMD echo $MYPATH ---> Running in 47664a0e6e10Removing intermediate container 47664a0e6e10 ---> 8db1cff1fad3Step 9/10 : CMD echo "success ------ ok" ---> Running in 7ad2234cdfbdRemoving intermediate container 7ad2234cdfbd ---> a08723e08f62Step 10/10 : CMD /bin/bash ---> Running in e0ecfa0bf1f3Removing intermediate container e0ecfa0bf1f3 ---> 77c006bf4b15Successfully built 77c006bf4b15Successfully tagged zhl/centos1.1:latestroot@zhanghl:/opt/docker/mydocker#
3 运行
docker run -it 新镜像名字:TAG .
root@zhanghl:/opt/docker/mydocker# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEzhl/centos1.1 latest 77c006bf4b15 3 minutes ago 291MBzhl/centos latest e4998e64dece 38 hours ago 209MBzhl/mytomcat 1.1 a636ea3caaed 4 days ago 672MBmongo latest 995ccc33e58f 8 days ago 449MBtomcat latest c0e850d7b9bb 9 days ago 667MBhello-world latest d1165f221234 8 weeks ago 13.3kBcentos latest 300e315adb2f 4 months ago 209MBroot@zhanghl:/opt/docker/mydocker# docker run -it 77c006bf4b15[root@01ba3472d1c3 local]# pwd/usr/local[root@01ba3472d1c3 local]# ifconfigeth0: flags=4163mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 21 bytes 2716 (2.6 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0[root@01ba3472d1c3 local]# vim a.txt[root@01ba3472d1c3 local]# cat a.txthello
4 列出镜像的变更历史
docker history [镜像名]
[root@01ba3472d1c3 local]# docker history 77c006bf4b15bash: docker: command not found[root@01ba3472d1c3 local]# exitexitroot@zhanghl:/opt/docker/mydocker# docker history 77c006bf4b15IMAGE CREATED CREATED BY SIZE COMMENT77c006bf4b15 7 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh">
CMD / ENTRYPOINT 镜像案例
都是指定一个容器启动时要运行的命令
CMD
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换
案例 tomcat 的讲解演示
追加 ls -l 命令后 替代了原理运行tomcat的命令,导致docker没有启动
ENTRYPOINT
docker run 之后的参数会被当做参数传递给 ENTRYPOINT,之后形成新的命令组合
案例
制作CMD版可以查询IP信息的容器
DockerFile: Dockerfile -myid
FROM centosRUN yum install -y curlCMD ["curl","www.trackip.net/ip?json"]
root@zhanghl:/opt/docker/mydocker# docker build -f Dockerfile-myid -t myid:1.1 .Sending build context to Docker daemon 3.072kBStep 1/3 : FROM centos ---> 300e315adb2fStep 2/3 : RUN yum install -y curl ---> Using cache ---> 82abeb79293fStep 3/3 : CMD ["curl","www.trackip.net/ip?json"] ---> Running in bafa2c73ec55Removing intermediate container bafa2c73ec55 ---> a566bc415a96Successfully built a566bc415a96Successfully tagged myid:1.1root@zhanghl:/opt/docker/mydocker# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmyid 1.1 a566bc415a96 5 seconds ago 243MBmyip latest 251ed5335c1a 30 minutes ago 243MBzhl/centos1.1 latest 77c006bf4b15 3 hours ago 291MBzhl/centos latest e4998e64dece 40 hours ago 209MBzhl/mytomcat 1.1 a636ea3caaed 4 days ago 672MBmongo latest 995ccc33e58f 8 days ago 449MBtomcat latest c0e850d7b9bb 9 days ago 667MBhello-world latest d1165f221234 8 weeks ago 13.3kBcentos latest 300e315adb2f 4 months ago 209MBroot@zhanghl:/opt/docker/mydocker# docker run -it myid:1.1{"IP":"175.161.93.164","Country":"CN","UA":"curl\/7.61.1","Time":1619934102}
问题 ,运行时 加参数 -i 报错
root@zhanghl:/opt/docker/mydocker# docker run -it myid:1.1 -idocker: Error response from daemon: OCI runtime create failed: container_linux.go:367: starting container process caused: exec: "-i": executable file not found in $PATH: unknown.
WHY
我们可以看到可执行文件找不到的报错,executable file not found。之前我们说过,跟在镜像名后面的是 command,运行时会替换 CMD 的默认值。因此这里的 -i 替换了原来的 CMD,而不是添加在原来的 curl -s http://ip.cn 后面。而 -i 根本不是命令,所以自然找不到。 那么如果我们希望加入 -i 这参数,我们就必须重新完整的输入这个命令: $ docker run myip curl -s http://ip.cn -i
制作ENTRYPOINT版查询IP信息的容器
DockerFile:
FROM centosRUN yum install -y curlENTRYPOINT ["curl","www.trackip.net/ip?json"]
build
root@zhanghl:/opt/docker/mydocker# docker build -f Dockerfile-Entrypoint-myip -t myip:1.2 .Sending build context to Docker daemon 4.096kBStep 1/3 : FROM centos ---> 300e315adb2fStep 2/3 : RUN yum install -y curl ---> Using cache ---> 82abeb79293fStep 3/3 : ENTRYPOINT ["curl","www.trackip.net/ip?json"] ---> Running in 70070b1d358cRemoving intermediate container 70070b1d358c ---> f1f60b285381Successfully built f1f60b285381Successfully tagged myip:1.2root@zhanghl:/opt/docker/mydocker#
运行
root@zhanghl:/opt/docker/mydocker# docker run -it myip:1.2{"IP":"175.161.93.164","Country":"CN","UA":"curl\/7.61.1","Time":1619934632}root@zhanghl:/opt/docker/mydocker# root@zhanghl:/opt/docker/mydocker# docker run -it myip:1.2 -iHTTP/1.1 200 OKDate: Sun, 02 May 2021 05:50:38 GMTContent-Type: text/plainContent-Length: 76Connection: keep-aliveSet-Cookie: __cfduid=d6e71854852b8ade1b5e9d1ba03386d6a1619934638; expires=Tue, 01-Jun-21 05:50:38 GMT; path=/; domain=.trackip.net; HttpOnly; SameSite=LaxCF-Cache-Status: DYNAMICcf-request-id: 09cd3a08d100000530688e1000000001Report-To: {"group":"cf-nel","max_age":604800,"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report?s=aZpOakyvJEJIy5RKJSanPc6kAxlXG390nfy3ADvHSEbFkG7pzavegW8Xwt7RiF%2F6ExbnXvvp9ZiGHKJ0gD%2F%2F6fm5IyWGJPv%2FeKG1mY%2FGnWQ%3D"}]}NEL: {"report_to":"cf-nel","max_age":604800}Server: cloudflareCF-RAY: 648ef9214d210530-LAXalt-svc: h4-27=":443"; ma=86400, h4-28=":443"; ma=86400, h4-29=":443"; ma=86400{"IP":"175.161.93.164","Country":"CN","UA":"curl\/7.61.1","Time":1619934639}root@zhanghl:/opt/docker/mydocker# root@zhanghl:/opt/docker/mydocker#
ONBUILD 命令案例
修改上一步的DockerFile
FROM centosRUN yum install -y curlENTRYPOINT ["curl","www.trackip.net/ip?json"]ONBUILD RUN echo "father images onbuild------886"
build镜像
docker build -f Dockerfile-Entrypoint-myip -t myip_father .
root@zhanghl:/opt/docker/mydocker# docker build -f Dockerfile-Entrypoint-myip -t myip_father .Sending build context to Docker daemon 5.12kBStep 1/4 : FROM centos ---> 300e315adb2fStep 2/4 : RUN yum install -y curl ---> Using cache ---> 82abeb79293fStep 3/4 : ENTRYPOINT ["curl","www.trackip.net/ip?json"] ---> Using cache ---> f1f60b285381Step 4/4 : ONBUILD RUN echo "father images onbuild------886" ---> Using cache ---> 1d20c7ac1ee1Successfully built 1d20c7ac1ee1Successfully tagged myip_father:latest
显示信息:
Step 4/4 : ONBUILD RUN echo "father images onbuild------886"
以myip:1.3 为父镜像 编写子镜像DockerFile。Dockerfile-Entrypoint-myip-sub
FROM myip_fatherRUN yum install -y curlENTRYPOINT ["curl","www.trackip.net/ip?json"]ONBUILD RUN echo "father images onbuild------886"~
docker build -f Dockerfile-Entrypoint-myip-sub -t myip_son .Sending build context to Docker daemon 5.12kBStep 1/4 : FROM myip_father# Executing 1 build trigger ---> Running in 9b6bfe884ccdfather images onbuild------886Removing intermediate container 9b6bfe884ccd ---> d45eda2663bcStep 2/4 : RUN yum install -y curl ---> Running in 3f4e383eec45Last metadata expiration check: 1:08:58 ago on Sun May 2 05:10:51 2021.Package curl-7.61.1-14.el8_3.1.x86_64 is already installed.Dependencies resolved.Nothing to do.Complete!Removing intermediate container 3f4e383eec45 ---> 4cdefe20ba39Step 3/4 : ENTRYPOINT ["curl","www.trackip.net/ip?json"] ---> Running in 395df3226201Removing intermediate container 395df3226201 ---> fc869c497482Step 4/4 : ONBUILD RUN echo "father images onbuild------886" ---> Running in 36d3ac20d0feRemoving intermediate container 36d3ac20d0fe ---> c3615df75130Successfully built c3615df75130Successfully tagged myip_son:latest
build时父类onbuild事件被触发
ONBUILD RUN echo "father images onbuild------886"
自定义镜像TOMCAT
1 创建实验目录 /opt/docker/mydocker/tomcat9
2 创建c.txt
touch c.txt
3 将jdk和tomcat安装的压缩包拷贝进目录
root@zhanghl:/opt/docker/mydocker/tomcat9# ll总用量 152772drwxr-xr-x 2 root root 4096 5月 2 16:33 ./drwxr-xr-x 3 root root 4096 5月 2 14:25 ../-rw-r--r-- 1 root root 11486964 5月 2 14:30 apache-tomcat-9.0.45.tar.gz-rw-r--r-- 1 root root 0 5月 2 14:28 c.txt-rw-r--r-- 1 root root 144935989 5月 2 16:31 jdk-8u291-linux-x64.tar.gzroot@zhanghl:/opt/docker/mydocker/tomcat9# pwd/opt/docker/mydocker/tomcat9
4 在目录下新建Dockerfile文件
FROM centosMAINTAINER ZHL<253316343@qq.com>#把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下COPY c.txt /usr/local/cincontainer.txt#把java与tomcat添加到容器中ADD jdk-8u291-linux-x64.tar.gz /usr/local/ADD apache-tomcat-9.0.45.tar.gz /usr/local/#安装vim编辑器RUN yum -y install vim#设置工作访问时候的WORKDIR路径,登录落脚点ENV MYPATH /usr/localWORKDIR $MYPATH#配置java与tomcat环境变量ENV JAVA_HOME /usr/local/jdk1.8.0_291ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarENV CATALINA_HOME /usr/local/apache-tomcat-9.0.45ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.45ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin#容器运行时监听的端口EXPOSE 8080#启动时运行tomcat# ENTRYPOINT ["/usr/local/apache-tomcat-9.0.45/bin/startup.sh" ]# CMD ["/usr/local/apache-tomcat-9.0.45/bin/catalina.sh","run"]CMD /usr/local/apache-tomcat-9.0.45/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.45/bin/logs/catalina.out
5 构建
docker build -f /opt/docker/mydocker/tomcat9/DockerFile -t mytomcat9 .
root@zhanghl:/opt/docker/mydocker/tomcat9# docker imagesREPOSITORY TAG IMAGE ID CREATED SIZEmytomcat9 latest 2b12a6a03ea0 2 minutes ago 643MB
6 RUN
docker run -d -p 9080:8080 --name myt9 -v /opt/docker/mydocker/tomcat9/test:/usr/local/apache-tomcat-9.0.45/webapps/test -v /opt/docker/mydocker/tomcat9/tomcat9logs/:/usr/local/apache-tomcat-9.0.45/logs mytomcat9
准备两个目录
root@zhanghl:/opt/docker/mydocker/tomcat9# mkdir testroot@zhanghl:/opt/docker/mydocker/tomcat9# mkdir tomcat9logsroot@zhanghl:/opt/docker/mydocker/tomcat9# ll总用量 152784drwxr-xr-x 4 root root 4096 5月 2 17:23 ./drwxr-xr-x 3 root root 4096 5月 2 14:25 ../-rw-r--r-- 1 root root 11486964 5月 2 14:30 apache-tomcat-9.0.45.tar.gz-rw-r--r-- 1 root root 0 5月 2 14:28 c.txt-rw-r--r-- 1 root root 1039 5月 2 16:40 DockerFile-rw-r--r-- 1 root root 144935989 5月 2 16:31 jdk-8u291-linux-x64.tar.gzdrwxr-xr-x 2 root root 4096 5月 2 17:23 test/drwxr-xr-x 2 root root 4096 5月 2 17:23 tomcat9logs/
7 验证
进入容器查看目录内容
root@zhanghl:/opt/docker/mydocker/tomcat9# docker exec 882930ee0ac0 ls -ltotal 52drwxr-xr-x 1 root root 4096 May 2 09:16 apache-tomcat-9.0.45drwxr-xr-x 2 root root 4096 Nov 3 15:22 bin-rw-r--r-- 1 root root 0 May 2 06:28 cincontainer.txtdrwxr-xr-x 2 root root 4096 Nov 3 15:22 etcdrwxr-xr-x 2 root root 4096 Nov 3 15:22 gamesdrwxr-xr-x 2 root root 4096 Nov 3 15:22 includedrwxr-xr-x 8 10143 10143 4096 Apr 7 19:26 jdk1.8.0_291drwxr-xr-x 2 root root 4096 Nov 3 15:22 libdrwxr-xr-x 3 root root 4096 Dec 4 17:37 lib64drwxr-xr-x 2 root root 4096 Nov 3 15:22 libexecdrwxr-xr-x 2 root root 4096 Nov 3 15:22 sbindrwxr-xr-x 5 root root 4096 Dec 4 17:37 sharedrwxr-xr-x 2 root root 4096 Nov 3 15:22 src
8 结合前述的容器卷将测试的web服务test发布
在宿主机中共享文件夹中创建Web服务
root@zhanghl:/opt/docker/mydocker/tomcat9/test# mkdir WEB-INFroot@zhanghl:/opt/docker/mydocker/tomcat9/test# cd WEB-INF/root@zhanghl:/opt/docker/mydocker/tomcat9/test/WEB-INF# vim web.xmlroot@zhanghl:/opt/docker/mydocker/tomcat9/test/WEB-INF# vim a.jsp
创建 WEB-INFO目录,并在其下创建 web.xml
web.xml:
test
在 test目录中创建 a.jsp:
Insert title here -----------welcome------------ <%="i am in docker tomcat self "%>
<% System.out.println("=============docker tomcat self");%>
重启 容器
docker restart [container id]
root@zhanghl:/opt/docker/mydocker/tomcat9/test/WEB-INF# docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES882930ee0ac0 mytomcat9 "/bin/sh -c '/usr/lo…" 17 minutes ago Up 17 minutes 0.0.0.0:9080->8080/tcp, :::9080->8080/tcp myt9root@zhanghl:/opt/docker/mydocker/tomcat9/test/WEB-INF# docker restart 882930ee0ac0
查看网页
查看日志
root@zhanghl:/opt/docker/mydocker/tomcat9/tomcat9logs# cat catalina.out
小总结
到此,关于"什么是Dockerfile"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!