一、是什么
Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。把镜像比喻成一个软件那么DockerFile就相当于是软件的配置文件。具体的内容可参考[官方网站](Dockerfile reference | Docker Documentation。
二、能做什么
通过使用Dockerfile,开发人员可以通过简单的文本文件定义和管理镜像的构建过程,实现自动化、可重复和可管理的镜像构建。Dockerfile提供了一种便捷且可扩展的方式来创建、配置和部署Docker镜像。
-
自动化构建:通过编写Dockerfile,可以自动构建Docker镜像,而无需手动逐步执行构建步骤。Docker根据Dockerfile中的指令顺序执行构建步骤,从而实现自动化构建过程。
-
可重复性:Dockerfile的存在可以确保镜像的构建过程是可重复的。通过编写一致的Dockerfile,可以确保不同环境下构建的镜像具有相同的配置和依赖关系,从而提高应用程序在不同环境中的可移植性和一致性。
-
配置管理:Dockerfile中的指令可以用于配置镜像的环境、安装所需的软件包和依赖项,以及设置运行时的参数。通过在Dockerfile中定义这些配置和依赖关系,可以更好地管理和跟踪镜像的配置,确保每次构建的镜像都具有相同的配置和依赖项。
-
版本控制:Dockerfile本身是一个文本文件,可以使用版本控制系统(如Git)对其进行管理和跟踪。通过对Dockerfile进行版本控制,可以轻松管理和回溯镜像构建过程中的变更,同时也方便团队协作和分享Docker镜像构建配置。
三、基础
- 每条保留字指令都必须为大写字母且后面要跟随至少一个参数。
- 指令顺序执行,遵循从上到下原则。
- #表示注释。
- 每条指令都会创建一个新的镜像层,并对镜像进行提交。
四、执行大致流程
- docker从基础镜像运行一个容器。
- 顺序执行一条指令对容器做出修改。
- 执行类似docker commit的操作提交一个新的镜像层。
- docker基于刚才提交的镜像运行一个新的容器。
- 执行DockerFile中下一条指令直到文件中的所有指令都执行完成。
五、指令详解
FROM
该指令初始化新的构建阶段,并为后续指令设置基础镜像。因此,一个 有效必须以指令开头。
RUN
构建镜像时运行的指令,有两种格式。
- RUN <命令行> eg:RUN yum -y install vim
- RUN [”可执行文件“,“参数1”,”参数2“]
CMD
指定容器启动后要干的事情,有三种格式。
- CMD [“可执行文件”,“参数1”,“参数2”]
- CMD [“参数1”,“参数2”]
- CMD <命令>
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。类似于RUN指令,用于运行程序,但是运行的时间点不同。CMD 在docker run 时运行,RUN 是在 docker build。
MAINTAINER
镜像维护者的姓名和邮箱地址。
EXPOSE
当前容器对外暴露出的端口。格式为。
- EXPOSE <端口1> [<端口2>…]
作用:帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
ENV
设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。格式为。
- ENV <键> = <值> …
- ENV <键> <值>
以下示例设置 NODE_VERSION = 7.2.0 , 在后续的指令中可以通过 $NODE_VERSION 引用:
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc"
ADD
将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包。ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
COPY
类似ADD,拷贝文件和目录到镜像中。将从构建上下文目录中<源路径> 的文件/目录复制到新的一层镜像内的<目标路径>位置,有两种格式。
- COPY <源文件> <目标文件>
- COPY [“源文件”,“目标文件”]
目标路径不用事先建好,会自动创建。
VOLUME
定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。有两种格式。
- VOLUME [“<路径1>”, “<路径2>”…]
- VOLUME <路径>
作用:避免重要的数据,因容器重启而丢失,这是非常致命的。避免容器不断变大。
ENTRYPOINT
类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序。格式有两种。
- ENTRYPOINT [“executable”, “param1”, “param2”]
- ENTRYPOINT command param1 param2
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
下面我将用一个案列来说明ENTRYPOINT搭配CMD的用法
假设已通过 Dockerfile 构建了 nginx:test 镜像:
FROM nginx
ENTRYPOINT ["nginx", "-c"] # 定参
CMD ["/etc/nginx/nginx.conf"] # 变参
1.不传参运行
$ docker run nginx:test
容器内会默认运行以下命令,启动主进程。
nginx -c /etc/nginx/nginx.conf
2、传参运行
$ docker run nginx:test -c /etc/nginx/new.conf
容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件)
nginx -c /etc/nginx/new.conf
所以说执行docker run命令指定了参数它就会用指定的参数,如果没有指定参数它就会使用DockerFile中指定的参数。
六、案例
需求:构建一个自己的centos镜像,使其具备vim+ifconfig+jdk8,登录后进入路径为/usr/local,运行生成容器时并暴露80端口。
实现步骤:
1.编写Dockerfile文件
需要准备一个jdk8的安装包,配置环境变量的时候以及把安装包添加到容器的时候要注意自己下载的jdk8的版本号,否则可能导致报错或者是环境变量配置失败。
Dockerfile的内容
FROM centos:7
MAINTAINER wenh<bertwenh@qq.com>
ENV MYPATH /usr/local
WORKDIR $MYPATH
#安装vim编辑器
RUN yum -y install vim
#安装ifconfig命令查看网络IP
RUN yum -y install net-tools
#安装java8及lib库
RUN yum -y install glibc.i686
RUN mkdir /usr/local/java
#ADD 是相对路径jar,把jdk-8u171-linux-x64.tar.gz添加到容器中,安装包必须要和Dockerfile文件在同一位置
ADD jdk-8u371-linux-x64.tar.gz /usr/local/java/
#配置java环境变量
ENV JAVA_HOME /usr/local/java/jdk1.8.0_371
ENV JRE_HOME $JAVA_HOME/jre
ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH
ENV PATH $JAVA_HOME/bin:$PATH
EXPOSE 80
CMD echo $MYPATH
CMD echo "success--------------ok"
CMD /bin/bash
2.构建
build 命令来构建自己的 centos 镜像
docker build -f /path/DataFile -t 镜像名 [:TAG] .
使用centos8会报这个错误,所以要用centos7来制做这个镜像。
注意:docker build -t centos:1.1 .这条命令后面是有一个空格和一个.的。
3.运行
run 命令来启动运行这个镜像生成的实例容器
docker run -it 镜像名[:TAG]
可以看到我们成功在centos中安装了jdk而且也成功的配置好了环境变量。