(精华)2020年10月31日 Docker Dockerfile详解

什么是 Dockerfile?

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

使用 Dockerfile 定制镜像
1、下面以定制一个 nginx 镜像(构建好的镜像内会有一个 /usr/share/nginx/html/index.html 文件)

在一个空目录下,新建一个名为 Dockerfile 文件,并在文件内添加以下内容:

FROM nginx
RUN echo '这是一个本地构建的nginx镜像' > /usr/share/nginx/html/index.html

在这里插入图片描述
2、FROM 和 RUN 指令的作用

FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
RUN:用于执行后面跟着的命令行命令。有以下俩种格式:
shell 格式:

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

exec 格式:

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

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

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

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

开始构建镜像
在 Dockerfile 文件的存放目录下,执行构建动作。

以下示例,通过目录下的 Dockerfile 构建一个 nginx:v3(镜像名称:镜像标签)。

注:最后的 . 代表本次执行的上下文路径,下一节会介绍。

其他命令详解

1:ENV

格式: ENV 或者 ENV = …

ENV指令可以为镜像创建出来的容器声明环境变量。并且在Dockerfile中,ENV指令声明的环境变量会被后面的特定指令(即ENV、ADD、COPY、WORKDIR、EXPOSE、VOLUME、USER)解释使用。

其他指令使用环境变量时,使用格式为 v a r i a b l e n a m e 或 者 variable_name或者 variablename{variable_name}。如果在变量面前添加斜杠\可以转义。如$foo或者${foo}将会被转换为 f o o 和 foo和 foo{foo},而不是环境变量所保存的值。另外,ONBUILD指令不支持环境替换。

2:COPY

格式: COPY

COPY指令复制所指向的文件或目录,将它添加到新镜像中,复制的文件或目录在镜像中的路径是。所指定的源可以有多个,但必须是上下文根目录中的相对路径。
不能只用形如 COPY …/something /something这样的指令。此外,可以使用通配符指向所有匹配通配符的文件或目录,例如,COPY home* /mydir/ 表示添加所有以”hom”开头的文件到目录/mydir/中。

可以是文件或目录,但必须是目标镜像中的绝对路径或者相对于WORKDIR的相对路径(WORKDIR即Dockerfile中WORKDIR指令指定的路径,用来为其他指令设置工作目录)。
若以反斜杠/结尾则其指向的是目录;否则指向文件。同理。若是一个文件,则的内容会被写到中;否则指向的文件或目录中的内容会被复制添加到目录中。
当指定多个源时,必须是目录。如果不存在,则路径中不存在的目录会被创建。

3:ADD

格式:ADD

ADD与COPY指令在功能上很相似,都支持复制本地文件到镜像的功能,但ADD指令还支持其他功能。可以是指向网络文件的URL,此时若指向一个目录,则URL必须是完全路径,这样可以获得网络文件的文件名filename,该文件会被复制添加到/。
比如 ADD http://example.com/config.property / 会创建文件/config.property。

还可以指向一个本地压缩归档文件,该文件会在复制到容器时会被解压提取,如ADD sxample.tar.xz /。但是若URL中的文件为归档文件则不会被解压提取。

ADD 和 COPY指令虽然功能相似,但一般推荐使用COPY,因为COPY只支持本地文件,相比ADD而言,它更加透明。

4:EXPOSE

格式: EXPOSE [/…]

EXPOSE指令通知Docker该容器在运行时侦听指定的网络端口。可以指定端口是侦听TCP还是UDP,如果未指定协议,则默认值为TCP。
这个指令仅仅是声明容器打算使用什么端口而已,并不会自动在宿主机进行端口映射,可以在运行的时候通过docker -p指定。

EXPOSE 80/tcp
EXPOSE 80/udp
复制代码

5:USER

格式: USER [:<group] 或者 USER [:]

USER指令设置了user name和user group(可选)。在它之后的RUN,CMD以及ENTRYPOINT指令都会以设置的user来执行。

6:WORKDIR

格式: WORKDIR /path/to/workdir

WORKDIR指令设置工作目录,它之后的RUN、CMD、ENTRYPOINT、COPY以及ADD指令都会在这个工作目录下运行。如果这个工作目录不存在,则会自动创建一个。
WORKDIR指令可在Dockerfile中多次使用。如果提供了相对路径,则它将相对于上一个WORKDIR指令的路径。例如

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
复制代码
输出结果是 /a/b/c

7:RUN

格式1: RUN (shell格式)
格式2: RUN [“executable”, “param1”, “param2”] (exec格式,推荐使用)

RUN指令会在前一条命令创建出的镜像的基础上创建一个容器,并在容器中运行命令,在命令结束运行后提交容器为新镜像,新镜像被Dockerfile中的下一条指令使用。

RUN指令的两种格式表示命令在容器中的两种运行方式。当使用shell格式时,命令通过/bin/sh -c运行。
当使用exec格式时,命令是直接运行的,容器不调用shell程序,即容器中没有shell程序。
exec格式中的参数会被当成JSON数组被Docker解析,故必须使用双引号而不能使用单引号。因为exec格式不会在shell中执行,所以环境变量的参数不会被替换。

比如执行RUN [“echo”, “ H O M E " ] 指 令 时 , HOME"]指令时, HOME"]HOME不会做变量替换。如果希望运行shell程序,指令可以写成 RUN [”/bin/bash", “-c”, “echo”, “$HOME”]。

8:CMD

CMD指令有3种格式。

格式1:CMD (shell格式)
格式2:CMD [“executable”, “param1”, “param2”] (exec格式,推荐使用)
格式3:CMD [“param1”, “param2”] (为ENTRYPOINT指令提供参数)

CMD指令提供容器运行时的默认值,这些默认值可以是一条指令,也可以是一些参数。一个Dockerfile中可以有多条CMD指令,但只有最后一条CMD指令有效。
CMD [“param1”, “param2”]格式是在CMD指令和ENTRYPOINT指令配合时使用的,CMD指令中的参数会添加到ENTRYPOING指令中.使用shell和exec格式时,命令在容器中的运行方式与RUN指令相同。

不同之处在于,RUN指令在构建镜像时执行命令,并生成新的镜像;CMD指令在构建镜像时并不执行任何命令,而是在容器启动时默认将CMD指令作为第一条执行的命令。如果用户在命令行界面运行docker run命令时指定了命令参数,则会覆盖CMD指令中的命令。

9:ENTRYPOINT

ENTRYPOINT指令有两种格式。

格式1:ENTRYPOINT (shell格式)
格式2:ENTRYPOINT [“executable”, “param1”, “param2”] (exec格式,推荐格式)

ENTRYPOINT指令和CMD指令类似,都可以让容器在每次启动时执行相同的命令,但它们之间又有不同。一个Dockerfile中可以有多条ENTRYPOINT指令,但只有最后一条ENTRYPOINT指令有效。

当使用Shell格式时,ENTRYPOINT指令会忽略任何CMD指令和docker run命令的参数,并且会运行在bin/sh -c中。这意味着ENTRYPOINT指令进程为bin/sh -c的子进程,进程在容器中的PID将不是1,且不能接受Unix信号。即当使用docker stop 命令时,命令进程接收不到SIGTERM信号。

推荐使用exec格式,使用此格式时,docker run传入的命令参数会覆盖CMD指令的内容并且附加到ENTRYPOINT指令的参数中。从ENTRYPOINT的使用中可以看出,CMD可以是参数,也可以是指令,而ENTRYPOINT只能是命令;另外,docker run命令提供的运行命令参数可以覆盖CMD,但不能覆盖ENTRYPOINT。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 猿与汪的秘密 设计师:上身试试 返回首页