Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。
基本结构
Dockerfile一般分为四部分:基础镜像信息,维护者信息,镜像操作指令,容器启动时执行指令。
Dockerfile由一行行命令语句组成,并且支持以#开头的注释行。
例子:
1 | #第一行必须指令基于的基础镜像 |
指令说明
FROM
指定所创建镜像的基础镜像,如果本地不存在,则默认从Docker Hub下载
格式为:FROM <image>或FROM <image>:<tag>或FROM <image>@<digest>
任何Dockerfile中第一条指令必须为FROM指令
若在同一个Dockerfile文件中创建多个镜像,可以使用多个FROM指令(每一个创建镜像使用一次)
MAINTAINER
指定维护者信息
格式:MAINTAINER <name>
该信息会写入生成镜像的Author属性域中
RUN
运行指定命令
格式:RUN <command>或RUN ["executable","param1","param2"]
前者在shell终端上运行,即/bin/sh -c
后者使用exec运行 ,不会启动shell环境。会被解析为json数组,必须使用双引号。可使用此方法指定使用其他终端类型,例:RUN ["/bin/bash", "-c","echo hello"]
每运行一条RUN指令,镜像就会添加新的一层,并提交
每条run指令在当前基础镜像执行,并且提交新镜像。当命令比较长时,可以使用\换行。 例:
1 | RUN apt update \ |
CMD
指定启动容器时默认执行的命令
格式:
CMD ["executable","param1","param2"]使用exec执行,推荐CMD command param1 param2在/bin/sh上执行 ,提供给需要交互的应用CMD ["Param1","param2"]提供给ENTRYPOINT做默认参数
每个Dockerfile只能执行一条CMD命令,多个CMD命令时,只最后一条被执行。
LABEL
指定生成镜像的元数据标签信息
格式:LABEL <key>=<value> <key>=<value>...
EXPOSE
声明镜像内服务所监听的端口
格式:EXPOSE <port> [<port>...]
该命令只起到声明作用,并不会自动完成端口映射。在启动容器时,指定-P或-p参数进行端口映射。
ENV
指定环境变量,在镜像生成过程中会被后续RUN指令使用,在镜像启动的容器中也会存在。
格式:ENV <key> <value>或ENV <key>=<value>...
此指令所指定的环境变量在容器运行时可被覆盖掉。如:
1 | docker run --env <key>=<value> image_name |
ADD
复制指定路径下的内容到容器中的指定路径下
格式:ADD <src> <dest>
<src>可以是Dockerfile所在目录的相对路径(文件或目录)或URL或tar文件(tar文件会自动解压到<dest>路径下)
<dest>可以是镜像内绝对路径,或相对于工作目录(WORKDIR)的相对路径
路径格式支持正则表达式
COPY
复制本地主机指定路径下的内容(为Dockerfile所在目录的相对路径,文件或目录)到镜像中的指定路径下。目标路径不存在时,会自动创建
路径格式支持正则表达式
ENTRYPOINT
指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数
格式:
ENTRYPOINT ["executable", "param1", "param2"](exec调用执行)ENTRYPOINT command param1 param2(shell中执行)
此时,CMD指令指定值将作为根命令的参数
每个Dockerfile只能执行一条ENTRYPOINT命令,多个ENTRYPOINT命令时,只最后一条被执行。
在运行容器时,此指令可被--entrypoint参数覆盖掉
VOLUME
创建一个数据卷挂载点
格式:VOLUME ["/data"]
创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据等
USER
指定运行容器时的用户名或UID,后续的 RUN 也会使用指定用户
格式:USER daemon
当服务不需要管理员权限时,可以通过该命令指定运行用户。并且可以在之前创建所需要的用户,例如:
1 | RUN groupadd -r postgres && useradd -r -g postgres postgres |
要临时获取管理员权限可以使用 gosu 或 sudo。
WORKDIR
为后续的 RUN 、 CMD 、 ENTRYPOINT 指令配置工作目录
格式为 WORKDIR /path/to/workdir
可以使用多个 WORKDIR 指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如
1 | WORKDIR /a |
则最终路径为 /a/b/c 。
ARG
指定一些镜像内使用的参数,这些参数在执行docker build命令时才以--build-arg <varname>=<value>格式传入
格式:ARG <name> [=<default value>]
ONBUILD
配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令
格式:ONBUILD [INSTRUCTION]
例:
Dockerfile1创建镜像A
1 | [...] |
Dockerfile2创建镜像B
1 | FROM A |
使用上方指令,会自动执行ONBUILD指令的内容,即FROM A指令等价于执行指令
1 | ADD . /app/src |
STOPSIGNAL
指定所创建镜像启动的容器接收退出的信号值
格式:STOPSIGNAL signal
HEALTHCHECK
配置所启动容器如何进行健康检查
格式:
HEALTHCHECK [OPTIONS] CMD command:根据所执行命令返回值是否为0来判断HEALTHCHECK NONE:禁止基础镜像中的健康检查
OPTIONS支持:
--interval=DURATION:检查的时间间隔(默认30s)--timeout=DURATION:每次检查等待结果的超时时间(默认30s)--retries=N:失败重试次数(默认3次)
SHELL
指定其他命令使用shell时的默认shell类型
格式:SHELL ["executable","parameters"]
默认值:["/bin/sh","-c"]
在Dockerfile中使用multi-stage
1 | FROM golang:1.7.3 as builder |
这个Dockerfile文件的特点是同时存在多个FROM指令,每个FROM指令代表一个stage的开始部分。我们可以把一个stage的产物拷贝到另一个stage中。
把第一个stage使用as语法命名为builder,然后在后面的stage中通过名称builder进行引用--from=builder
创建镜像
编写Dockerfile完成后,使用docker build命令创建镜像
格式:docker build [options] dir
过程:读取指定路径下(包括子目录)的Dockerfile,并将该目录下所有内容发送给Docker服务端,由服务端创建镜像。所以,除非特殊需要,一般建议放置Dockerfile的目录为空目录。
1 | docker build -t re/fi /tmp/docker_build/ |
使用.dockerignore文件
此文件用于让Docker忽略匹配路径下的目录和文件
1 | # comment |
实践经验
- 精简镜像用途
- 选用合适的基础镜像
- 提供足够清晰的命令注释和维护者信息
- 正确使用版本号
- 减少镜像层数
- 及时删除临时文件和缓存文件
- 提高生成速度
- 调整合理的指令顺序
- 减少外部源的干扰