Dockerfile中文名叫镜像描述文件,它属于脚本文件,定义了镜像的构建过程,我们通过读取Dockerfile中的指令安装步骤自动生成镜像。它包含一系列指令,用于描述如何从基础镜像构建出一个新的镜像,并在其中安装、配置和运行应用程序。Dockerfile通常以选择一个基础镜像作为起点开始。个人认为基础镜像的选择对于镜像的构建具有重要作用
Dockerfile使用指令来描述构建过程中需要执行的步骤,每个Dockerfile的指令都会在镜像中创建一个新的层。这些层是可复用的,当Dockerfile的内容没有改变时,构建过程可以从缓存中使用现有的层,从而加快构建速度。而这时又来谈谈与之相关的联合文件系统(UnionFS)吧!
用通俗易懂的话来讲,可以把联合文件系统比作卷心菜,大家都知道卷心菜是一层一层叠起来的,类似地,Docker镜像由多个文件系统层叠加在一起形成,每个层都可以独立地添加、删除或修改。联合文件系统的每一层都是只读的,并且按照一定的顺序叠加在一起,形成一个层次结构。最底层是一个基础镜像(Base Image),上面依次叠加各个层,最后形成一个可写的容器层(Container Layer)。每个层都是一个完整的文件系统,包含文件、目录和元数据。层之间是相互独立的,可以单独进行操作和管理。只有容器层是可写的,其他层都是只读的。当创建一个容器时,Docker会在镜像的基础上创建一个新的容器层。这个容器层可以在运行时进行读写操作,而其他层保持不变。这使得容器可以在不影响镜像的基础上运行和修改,这时是否又想到了commit命令。下图是拉取tomcat的式例:
Docker镜像的构建过程中,每个Dockerfile指令都会在镜像中创建一个新的层。这些层可以根据缓存机制进行重用,加快构建速度。当Dockerfile的指令未发生更改时,Docker可以直接使用缓存中的层,而不需要重新构建。不得不说,Dockerfile真香?。
Dockerfile的常见命令有FROM,RUN,COPY,ADD,WORKDIR,ENV,CMD,ENTRYPOINT,EXPOSE。FROM命令用于指定基础镜像。COPY和ADD虽然都能够用于将本地文件或目录复制到镜像中的指定路径,但ADD命令除了复制文件,还支持自动解压缩文件和URL下载等功能。RUN命令用作在容器中执行shell命令,命令格式有shell格式和exec格式,命令格式不光是RUN独有,而是下面的CMD和ENTRYPOINT都通用。shell命令格式为
RUN yum install -y nginx
exec命令格式为
RUN ["yum","-y","install","nginx"]
SHELL:当前shell是父进程,生成一个子shell进程去执行脚本,脚本执行完后退出子shell进程,回到当前父shell进程。
EXEC:用EXEC进程替换当前进程,并且保持PID不变,执行完毕后直接退出,不会退回原来的进程。
每个RUN命令都会在构建过程中创建一个新的层。ENV用于设置环境变量,比如
<strong>ENV MYPATH ~/local/java</strong>
我之前犯过一个可耻的错误。类似于这样
ENV MYPATH /etc/nginx/
COPY ~/nginx/myconf $MYPATH
注意,COPY命令不能将ENV定义的环境变量作为路径。这时咱又来谈谈更有意思的ENTRYPOIN和CMD命令。CMD命令和ENTRYPOINT命令都是在容器启动时进行的。Dockerfile中只有最后一个ENTRYPOINT会被执行,CMD同样也是。但不同的是,如果容器启动的时候有其他额外的附加指令,则CMD指令不生效。这也是有趣的一点,所以我可以这样写:
FROM centos
RUN ["echo", "image building!!!"]
ENTRYPOINT ["ps"]
CMD ["-ef"]
在你进行docker run的时候,你就可以手动来修改ps命令的参数,如
docker build -t luxy_docker .
docker run luxy_docker aux
EXPOSE命令用于声明容器内部的应用程序将监听的端口号,注意,只是申明,并不打开
总结来说,Dockerfile提供了一种声明式的方式来定义镜像构建过程,使得应用程序的部署变得更加可靠和可重复。通过编写和维护Dockerfile,开发者可以方便地构建、分享和部署应用程序及其依赖,并且能够确保在不同环境中具有一致的行为。