基本结构:

Dockerfile由一行行命令语句组成,并且支持以#开头的注释行

Dockerfile分为四部分:基础镜像信息,维护者信息、镜像操作指令和容器启动时执行的命令


Dockerfile指令说明

  • FROM:指定所创建镜像的基础镜像

  • MAINTAINER:指定维护者信息

  • RUN:运行命令

  • CMD:指定容器启动时默认执行的命令

  • LABEL:指定生成镜像的运数据标签信息

  • EXPOSE:声明镜像内服务所监听的端口

  • ENV:指定环境变量

  • ADD:复制指定的<src>路径下的内容到容器中的<dest>路径下,<src>可以为URL,如果为tar文件,会自动加压缩到<dest>路径下

  • COPY:复制本机的<src>路径下的内容到容器中的<dest>路径下,一般情况下推荐是用COPY而不是ADD

  • ENTRYPOINT:指定镜像的默认入口

  • VOLUME:创建数据卷挂载点

  • USER:指定运行容器时的用户名或者UID

  • WORKDIR:配置工作目录

  • ARG:指定镜像内使用的参数(例如版本号信息等)

  • ONBUILD:配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作命令

  • STOPSIGNAL:容器退出的信号值

  • HEALTHCHECK:如何进行健康检查

  • SHELL:指定使用shell时默认的shell类型


FROM

执行所创建镜像使用的基础镜像。如果本地不存在,会从配置Registry地址下载,格式为

FROM <image>

或者

FROM <image>:<tag>

或者

FROM <image>@<digest>

任何Dockerfile中的第一条指令必须为FROM指令。如果同一个Dockerfile创建多个镜像,可以使用多个FROM指令


MAINTAINER

指定维护者信息,格式为MAINTAINER<name>。例如:

MAINTAINER image_creator@docker.com

改信息会写入生成镜像的Author属性域中


RUN:

运行指定命令,格式为

RUN <command>

或者

 RUN ["executable", "param1", "param2"]

注意,后一个指令会被解析为Json数组,因此必须使用双引号。

前者默认将在shell终端中运行命令,即/bin/sh -c; 后者则使用exec执行,不会启动shell环境。

指定使用其他终端类型可以通过第二种方式实现,例如:RUN ["/bin/bash", "-c", "echo hello"]。

每条RUN指令将在当前镜像的基础上执行指定的命令,并提交为新的镜像,当命令较长时,可以使用“\”来换行,例如:

RUN apt-get update \
    && apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \
    && rm -rf /var/cache/apt


CMD:

CMD指令用来指定启动容器时默认执行的命令,它支持三种方式:

CMD ["executable", "param1", "param2"]使用exec执行,是推荐使用的方式
CMD command param1 param2 在/bin/sh中执行,提供给需要交互的应用
CDM [“param1”, "paam2"]提供给ENTRYPOINT的默认参数

每个Dockerfile只能有一条CMD命令,如果指定了多条命令,只有最后一条会被执行,如果启动容器时手动指定了运行的命令(作为run的参数),则会覆盖掉CMD指令的命令


LABEL

LABEL指令用来指定生成镜像的元数据标签信息

格式为

LABEL <key>=<value> <key>=<value> <key>=<value>...

例如:

LABEL version="1.0"
LABEL description="This text illustrates \ that lable-values can span multiple lines."


EXPOSE:

声明镜像内服务所监听的端口

格式为

EXPOSE <port> [<port>...]

例如:

EXPOSE 22 80 8443

注意:改指令只是起到声明作用,并不会完成端口映射。

在启动容器时使用-P,Docker会随机分配一个端口,转发到指定的端口,如果使用-p,则可以具体映射到宿主机本机的某个指定端口上。


ENV:

指定环境变量,在镜像生成过程中被后续的RUN指令所使用,在镜像启动的容器中也会存在。

格式为

 ENV <key><value>

或者

ENV <key>=<value>...

例如:

ENV PG_MAJOR 9.3
ENV PG_VERSION 9.3.4
RUN curl -SL http://example.com/postgres-$PG_VERSION.tar.xz | tar -xJC /usr/src/postgress &&...
ENV PATH /usr/local/postgres-$PG_MAJOR/bin:$PATH

指令指定的环境变量在运行时可以被覆盖掉,如

docker run --env <key>=<value> built_image


ADD:

改命令将复制指定的<src>路径下的内容到容器中的<dest>路径下

格式为

ADD <src> <dest>

其中<src>可以是Dockerfile所在目录的一个相对路径(文件或者目录),也可以是一个URL,

还可以是一个tar文件(如果为tar文件,会自动加压缩到<dest>路径下)。<dest>可以是镜像内的绝对路径,或相对于工作目录<WORKDIR>的相对路径


路径正则格式,如:

ADD *.c /code/


COPY:

格式为

COPY <src> <dest>

复制本地主机的<src>下的内容到镜像中的<dest>下,目录不存在时,会自动创建。路径同样支持正则格式。

当使用本地目录为源目录时,推荐使用COPY


ENTRYPOINT

指定镜像的默认入口命令,改入口命令会在容器启动时作为根命令执行,所有传入值作为该命令的参数

支持两种格式:

ENTRYPOINT ["EXECUTABLE", "param1" "param2"](exec调用执行)
ENTRYPOINT command  param1 param2(shell中执行)

此时,CMD指令指定值将作为根命令的参数

每个Dockerfile中只能有一个ENTRYPOINT,指定多个时,只有最后一个有效。(这点和CMD指令一样的)

在运行时,可以被--entrypoint参数覆盖掉,如docker run --entrypoint 


VOLUME:

创建一个数据卷挂载点

格式为

VOLUME ["/data"]

可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保存的数据等。


USER:

指定运行容器时的用户名或者UID,后续的RUN等指令也会使用指定的用户身份

格式为

USER daemon

当服务不需要管理员权限时,可以通过该命令指定运行用户,并且可以在之前创建所需要的用户,例如:

RUN groupadd -r postgres && useradd -r -g postgres

要临时获取管理员权限可以使用gosu或者sudo


WORKDIR:

为后续的RUN、CMD和ENTRYOINT指令配置工作目录

格式为

WORKDIR /path/to/workdir

可以使用多个WORKDIR指令,后续命令如果参数是相对路径,则会基于之前命令指定的路径。例如:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

最终路径为/a/b/c


ARG:

指定一些镜像内使用的参数(例如版本号信息等),这些参数在执行docker build命令时才以 --build-arg<varname>=<value>格式传入

格式为

ARG <name>[=<default value>]

则可以使用

docker build --build-arg<name>=<value>

来指定参数值


ONBUILD:

配置当所创建的镜像作为其他镜像的基础镜像时,所执行的创建操作指令。

格式为

ONBUILD [INSTRUCTION]

例如:Dockerfile使用如下的内容创建了镜像image-A;

[...]
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
[...]

如果基于image-A创建新的镜像时,新的Dockerfile中使用FROM image-A指定基础镜像,会自动执行ONBUILD指令的内容,等价于在后面添加了两条指令

FROM image-A
#Automatically run the following
ADD . /app/src
RUN /usr/local/bin/python-build --dir /app/src

使用ONBUILD指令的镜像,推荐在标签中注明,例如:ruby:1.9-onbuild


STOPSIGNAL:

指定所创建的镜像启动的容器接收退出的信号值

STOPSIGNAL signal


HEALTHECK

配置所启动的容器如何进行健康检查,格式有两种:

HEALTHCHECK [OPTIONS] CMD  command:根据所执行命令返回值是否为0来判断
HEALTHCHECK NONE:禁止基础镜像中的健康检查

OPTION支持

--interval=DURATION(默认为:30s):过多久检查一次
--timeout=DURATION(默认为:30s):每次检查等待结果的超时
--retries=N(默认为:3):如果失败了,重试几次才最终确定失败


SHELL:

执行其他命令使用shell时的默认shell类型

SHELL ["executable", "parameters"]

默认值为["/bin/sh", "-c"]



docker build创建镜像

基本格式为

docker build [选项] 内容路径

该命令将读取指定路径下(包括子目录)的dockerfile,并将改路径下的所有内容发送给Docker服务端,由服务端来创建镜像。

因此除非生成镜像需要,否则一般建议放置Dockerfile的目录为空目录。有两点经验:

  • 如果使用非内容路径下的Dockerfile,可以使用-f选项来指定其路径

  • 要指定生成镜像的的标签信息,可以使用-t选项

例如:指定Dockerfile所在路径为/tmp/docker_builder/,并且希望生成镜像标签为build_repo/first_image,可以使用下面的命令

docker build -t build_repo/first_image  /tmp/docker_builder/


Docker Hub 上的Dockerfile样例

https://hub.docker.com/search/?isAutomated=0&isOfficial=0&page=1&pullCount=0&q=Dockerfile&starCount=0

例如:

image.png



使用.dockerignore文件

.dockerignore用来忽略上下文目录中包含的一些image用不到的文件,它们不会传送到docker daemon。规则使用go语言的匹配语法。如:

# cat .dockerignore 
*.rpm
tmp*

这会将上下文目录下所有.rpm和tmp.*的文件排除掉

例如:

# cat Dockerfile 
FROM centos:6
MAINTAINER zengcp
WORKDIR /srv
#RUN yum -y install vim wget 
LABEL version="1.0"
EXPOSE 22 80 
ENV JDK_VERSION 1.8
#COPY ./jdk-8u151-linux-x64.rpm  /srv/
copy . ./
VOLUME "/data"


# ls
aaa.temp  Dockerfile  jdk-8u151-linux-x64.rpm  temp  tmpaaa

这里会将jdk的rpm包和tmpaaa文件排除