什么是 Dockerfile?

Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。

Dockerfile的基本结构

Dockerfile 一般分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令,’#’ 为 Dockerfile 中的注释。

使用 Dockerfile 定制镜像

这里仅讲解如何运行 Dockerfile 文件来定制一个镜像,具体 Dockerfile 文件内指令详解,将在下一节中介绍,这里你只要知道构建的流程即可。

1、下面以定制一个 nginx 镜像
在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:
image.png
FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
RUN:用于执行后面跟着的命令行命令。有以下俩种格式:
shell 格式:

  1. RUN <命令行命令>
  2. # <命令行命令> 等同于,在终端操作的 shell 命令。

exec 格式:

  1. RUN ["可执行文件", "参数1", "参数2"]
  2. # 例如:
  3. # RUN ["./test.php", "dev", "offline"] 等价于 RUN ./test.php dev offline

Dockerfile 的指令每执行一次都会在 docker 上新建一层。所以过多无意义的层,会造成镜像膨胀过大。

  1. FROM centos
  2. RUN yum install wget
  3. RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
  4. RUN tar -xvf redis.tar.gz
  5. 以上执行会创建 3 层镜像。可简化为以下格式:
  6. FROM centos
  7. RUN yum install wget \
  8. && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
  9. && tar -xvf redis.tar.gz

如上,以&&符号连接命令,这样执行后,只会创建 1 层镜像。

开始构建镜像

在 Dockerfile 文件的存放目录下,执行构建动作。
以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3(镜像名称:镜像标签)。
:最后的.代表本次执行的上下文路径,下一节会介绍。

  1. [root@Vue file]# docker build -t nginx:v0.1 .
  2. -t 镜像名称:tag

编译成功
image.png
image.png

上下文路径

上一节中,有提到指令最后一个 . 是上下文路径,那么什么是上下文路径呢?
上下文路径,是指 docker 在构建镜像,有时候想要使用到本机的文件(比如复制),docker build 命令得知这个路径后,会将路径下的所有内容打包。
解析:由于 docker 的运行模式是 C/S。我们本机是 C,docker 引擎是 S。实际的构建过程是在 docker 引擎下完成的,所以这个时候无法用到我们本机的文件。这就需要把我们本机的指定目录下的文件一起打包提供给 docker 引擎使用。
如果未说明最后一个参数,那么默认上下文路径就是 Dockerfile 所在的位置。
注意:上下文路径下不要放无用的文件,因为会一起打包发送给 docker 引擎,如果文件过多会造成过程缓慢。

Dockerfile 指令详解

COPY 复制指令,从上下文目录中复制文件或者目录到容器里指定路径。

  1. COPY [源路径] [目标路径]

COPY
需要在Dockerfile文件的构建的上下文中的相对路径、
image.png
docker镜像打包的COPY 指令将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置。实际操作中正确的方式和错误的方式参考如下:
正确:COPY ./package.json /app/COPY package.json /usr/src/app/
错误:COPY ../package.json /app或者 COPY /opt/xxxx /app
所以Dockerfile一般都是放在根目录下,COPY的文件使用相对路径。建议本地先调试好Dockerfile打包没问题后再迁移到CodePipeline上使用

image.png

ADD
ADD 指令和 COPY 的使用格式一致(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:

  • ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
  • ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
    1. ADD redis-5.0.12.tar.gz /home
    image.png

CMD 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:

  • CMD 在docker run 时运行。
  • RUN 是在 docker build。

作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效
CMD
CMD [“<可执行文件或命令>”,”“,”“,…]
CMD [““,”“,…] # 该写法是为 ENTRYPOINT 指令指定的程序提供默认参数
推荐使用第二种格式,执行过程比较明确。第一种格式实际上在运行的过程中也会自动转换成第二种格式运行,并且默认可执行文件是 sh。

指令:MAINTAINER功能描述:设置镜像作者语法:MAINTAINER < name>

https://www.cnblogs.com/liangyy09/p/13953001.html

WORKDIR

WORKDIR 是指下面的指令都在WORKDIR 指定目录下面工作,这个与linux 里面的cd 差不多
WORKDIR 目录

  1. FROM nginx
  2. WORKDIR test /home/
  3. RUN echo "这是一个Dockerfile" > /usr/share/nginx/html/index.html

可以看到已经是进入了 WORKDI设置的目录里面了
image.png

EXPOSEEXPOSE 指令用于暴露容器里的端口,我们在3.5里面演示过了,nginx暴露的端口是80,但是启动容器的时候需要指定宿主机端口来映射你暴露的端口。需要暴露多个端口的话可以使用多个EXPOSE,也可以一个EXPOSE指令后面跟多个端口,端口之间用空格隔开。
EXPOSE 端口

  1. FROM nginx
  2. WORKDIR /home
  3. EXPOSE 80 443 3306
  4. RUN echo "这是一个Dockerfile" > /usr/share/nginx/html/index.html

image.png

ENV

ENV指令是用于设置环境变量的

  1. ENV key=value
  2. ENV key value

RUN

RUN指令用于在容器中执行命令。我们常用来安装基础软件。
RUN 需要执行命令

VOLUME

定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:

  • 避免重要的数据,因容器重启而丢失,这是非常致命的。
  • 避免容器不断变大。

格式:
VOLUME [“<路径1>”, “<路径2>”…]
VOLUME <路径>