当前位置:   article > 正文

Docker——Dockerfile的理解 & 案例实操_dockerfile示例

dockerfile示例

文章目录:

1.Dockerfile是什么?

2.Dockerfile体系结构

3.案例实操

3.1 案例一(FROM、MAINTAINER、RUN、EXPOSE、WORKDIR、ENV、CMD)

3.2 案例二(CMD、ENTRYPOINT)

3.3 案例三(ONBUILD)

3.4 案例四(自定义tomcat9镜像)

4.小总结


1.Dockerfile是什么?

Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本。

整个Docker镜像的构建过程是:编写Dockerfile文件 → docker build → docker run。

Dockerfile文件的具体内容,我们以centos镜像为例,链接:https://github.com/CentOS/sig-cloud-instance-images/blob/b2d195220e1c5b181427c3172829c23ab9cd27eb/docker/Dockerfile

Dockerfile内容的基础知识:

  • 每条保留字指令都必须为大写字母且后面要跟随至少一个参数。
  • 指令按照从上到下,顺序执行。
  • #表示注释。
  • 每条指令都会创建一个新的镜像层,并对锐像进行提交。

Docker执行Dockerfile的具体流程:

  • docker从基础镜像运行一个容器。
  • 执行一条指令并对容器作出修改。
  • 执行类似docker commit的操作提交一个新的镜像层。
  • docker再基于刚提交的镜像运行一个新容器。
  • 执行dockerfile中的下一条指令直到所有指令都执行完成。

从应用软件的角度来看,Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段,

  • Dockerfile是软件的原材料。
  • Docker镜像是软件的交付品。
  • Docker容器则可以认为是软件的运行态。

Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

1. Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
 
2. Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时,会真正开始提供服务;
 
3. Docker容器,容器是直接提供服务的。


2.Dockerfile体系结构

  • FROM——基础镜像,当前新镜像是基于哪个镜像的
  • MAINTAINER——锐像维护者的姓名和邮箱地址
  • RUN—容器构建时需要运行的命令
  • EXPOSE ——当前容器对外暴露出的端口
  • WORKDIR——指定在创建容器后,终端默认登陆的进来工作目录,一个落脚点
  • ENV——用来在构建镜像过程中设置环境变量(ENV MY_PATH /usr/mytest    WORKDIR $MY_PATH)
  • ADD——将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包
  • COPY——类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置
  • VOLUME——容器数据卷,用于数据保存和持久化工作
  • CMD——指定一个容器启动时要运行的命令。Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换
  • ENTRYPOINT——指定一个容器启动时要运行的命令。ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数
  • ONBUILD——当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发

3.案例实操

3.1 案例一(FROM、MAINTAINERRUNEXPOSEWORKDIRENVCMD

首先,我这里先run一个centos镜像,以它为模板创建一个centos容器实例运行。

但是运行进入docker中的centos终端之后,发现之前在linux中常用的vim、ifconfig这些命令都用不了,此时pwd位于根目录下。

我这里要做的修改是使得vim、ifocnfig这两个命令在docker的centos容器中生效,同时当我进入这个容器时,不再位于根目录/下,而是直接到达/usr/local目录下

这就需要创建新的Dockerfile文件,之后build出一个新的镜像,最后run运行。

上面是Dockerfile文件的内容,创建完之后,下面执行docker build,以Dockerfile2文件构建出一个新的自定义的centos镜像。

构建成功,可以docker images查看一下。

三步走(编写Dockerfile → docker build → docker run),我们已经走完了前两步,最后就可以run了。

可以看到以我们刚刚新构建的镜像为模板生产出一个自定义的centos容器实例,进入之后,pwd看到当前工作目录为 /usr/local,同时,vim可以正常的编写文件,ifconfig也可以查出ip、网卡等相关信息。

这里还可以使用docker history可以查看该容器的构建过程、变更历史。

3.2 案例二(CMD、ENTRYPOINT)

首先,我们看一下tomcat官方镜像的Dockerfile文件,链接:https://github.com/docker-library/tomcat/blob/fb2ffad09f315bde50308816f7d84897b856e164/9.0/jdk8/corretto/Dockerfile

可以看到这个Dockerfile文件的最后一行是

CMD ["catalina.sh", "run"]

而我这里docker run这个tomcat,在命令的最后添加一个ls -l,那么此时就相当于在这个tomcat的Dockerfile文件的最后一行添加了 CMD ls -l,此时变成了

  1. CMD ["catalina.sh", "run"]
  2. CMD ls -l

由于Dockerfile文件中关于RUN的定义是:CMD——指定一个容器启动时要运行的命令。Dockerfile中可以有多个CMD指令,但只有最后一个生效,CMD会被docker run之后的参数替换。

所以下面的截图中,我这样去run,ls -l顺利的查出了/usr/local/tomcat目录下的内容。但是docker ps却显示当前并没有容器实例在运行,这就说明它的Dockerfile文件的倒数第二行的 CMD ["catalina.sh", "run"] 已经被 CMD ls -l 覆盖了。

上面演示了Dockerfile文件中如果存在多个CMD了话,那么只有最后一个CMD生效。

下面再来说说和CMD很像的ENTRYPOINT:ENTRYPOINT——指定一个容器启动时要运行的命令。ENTRYPOINT的目的和CMD一样,都是在指定容器启动程序及参数。

ENTRYPOINT并不会像CMD那样覆盖前面的命令参数,而是会追加,如果有一个ENTRYPOINT就正常执行,如果有第二个ENTRYPOINT就追加到第一个的后面,一同执行。

curl命令可以用来执行下载、发送各种HTTP请求,指定HTTP头部等操作。如果系统没有curl可以使用yum install curl安装,也可以下载安装。curl是将下载文件输出到stdout。

3.3 案例三(ONBUILD)

ONBUILD——当构建一个被继承的Dockerfile时运行命令,父镜像在被子继承后父镜像的onbuild被触发。

这里首先创建一个Dockerfile3文件,然后以centos为基础镜像构建一个自定义的新镜像myip_father,然后再创建一个Dockerfile4文件,这里就不再以centos为基础镜像了,也就不再是FROM centos,而是FROM myip_father,即此时镜像myip_son继承了myip_father。

最后当我docker build构建这个子镜像myip_son的时候,可以看到父镜像中ONBUILD后面的 RUN echo "father onbuild-------666" 这句话被打印出来了。

3.4 案例四(自定义tomcat9镜像)

上面已经介绍了很多Dockerfile中的命令,还差ADD、COPY,这两个在此案例中讲解。

ADD——将宿主机目录下的文件拷贝进镜像且ADD命令会自动处理URL和解压tar压缩包。

COPY——类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中 <源路径>的文件/目录复制到新的一层的镜像内的<目标路径>位置。

说的明白点:比如我们在淘宝买东西,最终肯定是以快递的方式送达,ADD就是指快递员给你送货到家之后,他帮你把快递拆开;COPY则是指快递员给你送货到家之后,他不会拆封,由你自己来拆封。

因为我们要自定义tomcat9,所以就需要两个压缩包(tomcat、jdk),我这里先级联创建了一个测试目录,然后将压缩包拷贝过来用作测试(先不解压)。

要构建新的tomcat镜像,第一步必然是编写Dockerfile文件。

  1. FROM centos
  2. MAINTAINER szh<2656307671@qq.com>
  3. #把宿主机当前上下文的c.txt拷贝到容器/usr/local/路径下
  4. COPY c.txt /usr/local/cincontainer.txt
  5. #把java与tomcat添加到容器中
  6. ADD jdk-8u121-linux-x64.tar.gz /usr/local/
  7. ADD apache-tomcat-9.0.13.tar.gz /usr/local/
  8. #安装vim编辑器
  9. RUN yum -y install vim
  10. #设置工作访问时候的WORKDIR路径,登录落脚点
  11. ENV MYPATH /usr/local
  12. WORKDIR $MYPATH
  13. #配置java与tomcat环境变量
  14. ENV JAVA_HOME /usr/local/jdk1.8.0_121
  15. ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
  16. ENV CATALINA_HOME /usr/local/apache-tomcat-9.0.13
  17. ENV CATALINA_BASE /usr/local/apache-tomcat-9.0.13
  18. ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/lib:$CATALINA_HOME/bin
  19. #容器运行时监听的端口
  20. EXPOSE 8080
  21. #启动时运行tomcat
  22. # ENTRYPOINT ["/usr/local/apache-tomcat-9.0.13/bin/startup.sh" ]
  23. # CMD ["/usr/local/apache-tomcat-9.0.13/bin/catalina.sh","run"]
  24. CMD /usr/local/apache-tomcat-9.0.13/bin/startup.sh && tail -F /usr/local/apache-tomcat-9.0.13/bin/logs/catalina.out

此时当前目录下有两个压缩包、c.txt、Dockerfile文件,先说明一下,这两个压缩包后面对应的就是ADD命令,因为ADD会在拷贝压缩包的同时帮你解压;c.txt文件对应的是COPY命令,只是单纯的拷贝。

然后我们docker build以此Dockerfile文件来构建自定义的tomcat9镜像。

构建完成之后,可以docker images查看一下。

下面的docker run命令:

  • -d是以守护式容器的方式启动,即后台启动(-it则是交互式容器,即前台启动)
  • -p指定docker中映射tomcat的端口为1234
  • --name对以此镜像生产的容器实例重命名
  • -v则是在容器中添加数据卷(以实现宿主机和docker容器之间的数据持久化 + 数据共享)
  • 这里只所以可以写多个-v,在容器中添加多个数据卷,就依赖于后面的 --privileged=true
  • 最后的szh-tomcat9是我们要以哪个镜像为模板生产容器实例运行

run之后,可以docker ps查看一下当前运行的容器实例。

 此时,到浏览器中,虚拟机ip + -p中映射的端口号即可访问tomcat的主页。

由于我们docker run -d是后台启动,并不像docker run -it前台启动那样直接进入tomcat的目录下。

所以这里可以使用docker exec命令进入正在运行的某个容器实例,后面添加了 ls -l,就覆盖了上一个CMD。

下面,我们可以尝试着在docker中的这个tomcat容器中部署一个简单的web服务,对应test目录。

在WEB-INF目录下,创建web服务所需的web.xml,在<display-name>标签中声明该web服务对外的名称为test。

退出WEB-INF目录,创建一个a.jsp的简单页面。

  1. <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  3. <html>
  4. <head>
  5. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  6. <title>Insert title here</title>
  7. </head>
  8. <body>
  9. -----------welcome------------
  10. <%="i am in docker tomcat self "%>
  11. <br>
  12. <br>
  13. <% System.out.println("=============docker tomcat self");%>
  14. </body>
  15. </html>

因为我们在这个tomcat容器中添加了部分文件,所以这里需要docker restart重启一下这个容器。

重启之后,到浏览器中,访问刚刚<display-name>标签对应的web服务的别名,即/test/a.jsp。

可以看到前台打出了 -----------welcome------------
                                 <%="i am in docker tomcat self "%> 信息。

而后台打印的信息则是在下面截图中的路径下,<% System.out.println("=============docker tomcat self");%>。


4.小总结

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/834616
推荐阅读
相关标签
  

闽ICP备14008679号