Dockerfile使用基本的基于DSL(Domain Specific Language)语法的指令来构建一个Docker镜像。

FROM

FROM一定是第一条指令,用来指定一个基准镜像。如果不想使用基准镜像,那么可以使用scratch,它是一个虚拟镜像,表示一个空白的镜像

FROM <registry>:<tag>

RUN

RUN指令用来在容器构建过程中运行一个命令。

RUN <command>
RUN ["<executable>","<param1>","<param2>"]

# 在第一个方式中,command通常是一个shell命令,以`/bin/sh -c`的方式运行。

每个RUN指令都会生成一层文件系统,所以常规的做法是将多个命令在一个RUN指令中执行

RUN ["/bin/bash","-c","apt-get update && apt-get install -y redis-server"]

EXPOSE

EXPOSE指令用来设置对外的端口。

EXPOSE <port>[/protocol]

其中protocol是指协议,值为tcp或udp,默认为tcp。多个端口以空格分隔可以同时暴漏多个端口。

CMD

CMD指令用于指定一个容器启动时要运行的命令。

CMD ["/bin/bash"]

CMD ["/bin/bash","-c","apt update"]  // 指定参数

使用docker run命令可以覆盖CMD命令,如果我们在Dockerfile中指定了CMD命令,而同时在docker run命令行中也指定了要运行的命令,命令行中指定的命令会覆盖Dockerfile中的命令。

在Dockerfile中只能指定一条CMD命令,如果指定了多条CMD命令,也只有最后一条指令会被执行。如果想在启动容器时运行多个进程或者多条命令,可以考虑使用类似Supervisor这样的服务管理工具。

ENTRYPOINT

ENTRYPOINT指令也用于指定一个容器启动时要运行的命令。

ENTRYPOINT ["/usr/sbin/nginx"]

ENTRYPOINT ["/usr/sbin/nginx","-g","daemon off;"]  // 指定参数

ENTRYPOINT指令与CMD指令非常类似,但ENTRYPOINT指令提供的命令不会被docker run命令行中提供的指令覆盖,docker run命令行中指定的任何参数都会被当做参数再次传递给ENTRYPOINT指令中指定的命令。

如果确实需要,可以在运行时通过docker run中的--entrypoint标志覆盖ENTRYPOINT指令。

WORKDIR

WORKDIR指令用来在从镜像创建一个新容器时,在容器内部设置一个工作目录,ENTRYPOINT和CMD指定的程序会在这个目录下执行。也可以为最终的容器设置工作目录。

ENV

ENV指令用来在镜像构建过程中设置环境变量

ENV RVM_PATH /home/rvm

这个新的环境变量可以在后续的任何RUN指令中使用。这些环境变量会被持久的保存到从我们的镜像创建的任何容器中。

在使用docker run运行时可以通过-e标志来传递环境变量,值当次有效。

USER

USER指令用来指定该镜像会以什么样的用户去运行。默认用户为root

在使用docker run运行时可以通过-u标志来覆盖USER指令的值。

VOLUME

VOLUME指令用来向基于镜像创建的容器添加卷。一个卷时可以存在于一个或者多个容器内的特定的目录,这个目录可以绕过联合文件系统,并提供如下共享数据或者对数据进行持久化的功能。

  • 卷可以在容器间共享和重用。
  • 一个容器不必和其他容器共享卷。
  • 对卷的修改是立即生效的。
  • 对卷的修改不会对更新镜像产生影响。
  • 卷会一直存在直到没有任何容器再使用它。

卷可以让我们将数据(如源代码,应用程序)、数据库、日志或者其他内容添加到镜像中而不是将这些内容提交到镜像中,并且允许我们在多个容器间共享这些内容。

VOLUME ["/data/project"]

VOLUME ["/data/project","/data/logs"]

ADD

ADD指令用来将构建环境下的文件和目录复制到镜像中。比如我们在使用nginx构建静态网站时需要更新配置文件nginx.conf

ADD nginx.conf /etc/nginx/
ADD admin.docker.com.conf /etc/nginx/conf.d/

在ADD文件时,docker通过目的地址参数末尾的字符来判断是目录还是文件。如果目标地址以/结尾,那么docker就认为目标地址指向目录,如果不以/结尾,那么docker就认为目标地址指向的是文件。

文件源也可以使用URL的格式:

ADD http://wordpress.org/latest.zip /data/wordpress.zip

如果将一个压缩文件(gzip,bzip2,xz)指定为源文件,docker会自动将压缩文件解压。

ADD latest.tar.gz /home/www/wordpress

上述命令会将压缩文件latest.tar.gz解压到/home/www/workpress目录下。docker解压文件的行为和使用带-x选项的tar命令一样。

如果目的位置的目录下存在同名的目录和文件,那么目的位置中的目录和文件不会被覆盖。如果目的位置不存在,docker将会自动创建全路径,将创建的文件和目录权限为0755。

ADD指令会使缓存变得无效

COPY

COPY指令非常类似与ADD,它们根本的不同是COPY只关心在构建上下文中复制本地文件,而不会去做文件提取和解压。

COPY conf.d/ /etc/apache/

文件源路径必须是一个与当前构建环境相对的文件或者目录,本地文件都会放到和Dockerfile同一个目录下。不能复制该目录之外的任何文件,因为构建环境将会上传到Docker守护进程,而复制是发生在守护进程中,任何位于构建环境之外的东西都是不可用的。目的位置必须是一个容器内部的绝对路径。

LABEL

LABEL指令用于为Docker镜像添加元数据。元数据以键值对的形式展现。可以在一个命令中添加多个键值对,以空格分隔。可以通过docker inspect命令查看镜像中的标签信息。

LABEL author="liumurong" version="1.0.0"

STOPSIGNAL

STOPSIGNAL指令用来设置停止容器时发送什么系统调用信号给容器。这个信号必须时内核系统调用表中合法的值。

ARG

ARG指令用来定义可以在docker build命令运行时传递给构建运行时的变量,我们只需要在构建时使用--build-arg标志即可。用户只能在构建时指定在Dockerfile中定义过的参数。

#添加指令
ARG build    
ARG webapp_user=user

#使用指令
docker build --build-arg build=1111 -t "imagename"

参数build将会被设置为1111,webapp_user将会继承默认值user

Docker预定义了一组ARG变量,可以在构建时直接使用。

  • HTTP_PROXY
  • HTTPS_PROXY
  • FTP_PROXY
  • NO_PROXY
  • http_proxy
  • https_proxy
  • ftp_proxy
  • no_proxy

ONBUILD

ONBUILD指令可以为镜像添加触发器。当一个镜像被用作其他镜像的基础镜像时,该镜像中的触发器会被执行。

触发器会在构建过程中插入新指令,我们可以认为这些指令是紧跟在FROM之后执行的。触发器可以是任何构建指令:

ONBUILD ADD . /home/www

当有镜像基于此镜像构建时,新的镜像会使用ADD指令将构建环境所在的目录下的全部内容添加到镜像中的/home/www目录下。我们可以使用这个镜像作为通用的静态Web应用的基准镜像。

ONBUILD触发器会按照在父镜像中指定的顺序执行,并且只能被继承一次,也就是说只能在子镜像中执行,而不会在孙子镜像中执行。

FROM,MAINTAINER,ONBUILD指令不能用在ONBUILD中,防止递归调用。