指令格式有两种:注释和指令,注释以 # 号开头,后面跟上信息
指令以大写的指令名开头,后面跟上参数

Dockerfile 示例

# Base images 基础镜像
FROM centos:7

#维护者信息
LABEL org.opencontainers.image.authors="kinoko"

#ENV 设置环境变量
ENV PATH /usr/local/nginx/sbin:$PATH

#ADD 文件放在当前目录下,拷过去会自动解压
ADD nginx-1.9.2.tar.gz /usr/local/
ADD epel-release-latest-7.noarch.rpm /usr/local/

#RUN 执行以下命令
RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm \
    && yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre \
    && yum clean all
RUN useradd -s /sbin/nologin -M www

#WORKDIR 相当于cd
WORKDIR /usr/local/nginx-1.9.2

RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre \
    && make \
    && make install
RUN echo "daemon off;" >> /etc/nginx.conf

#EXPOSE 映射端口
EXPOSE 80

#CMD 运行以下命令
CMD ["nginx"]

常见的指令

FROM

两种形式如下:

FROM <IMAGE>
FROM <IMAGE>:<TAG>

通过 FROM 指定的镜像名称必须是一个已经存在的镜像,这个镜像称之为基础镜像,必须位于第一条非注释指令

MAINTAINER

MAINTAINER <NAME>

指定镜像的作者信息,包含镜像的所有者和联系人信息,例如:MAINTAINER kinoko。由于 LABEL 指令更加灵活,所以该指令现在已经被废弃了。可以使用:`LABEL org.opencontainers.image.authors="kinoko"`` 代替。

RUN

用于指定构建镜像时运行的命令,两种模式:

RUN <command> (shell模式)
RUN ["executable", "param1", "param2"] (exec模式)

在 shell 模式下,是使用 /bin/sh -c COMMAND 来运行命令的
在 exec 模式下可以指定其他的 shell 来运行命令 RUN ["/bin/bash", "-c", "echo hello"]

多条 RUN 指令可以合并为一条:

RUN yum install net-tools && yum install ftp

这样在构建的时候会减少产生中间层镜像

EXPOSE

指定运行该镜像的容器使用的端口,可以是多个:

EXPOSE <PORT>

使用这个指令的目的是告诉应用程序容器内应用程序会使用的端口,在运行时还需要使用 -p 参数指定映射端口。这是 docker 处于安全的目的,不会自动打开端口。

docker run -p 80 -d dockertest/dockerfile_build nginx -g "daemon off"

CMD

用于提供容器运行的默认命令,如果在 docker run 时指定了运行的命令,则 CMD 命令不会执行。
CMD 有三种模式:

CMD <command> (shell模式)
CMD ["executable", "param1", "param2"] (exec模式)
CMD ['param1', 'param2'] (通常与 ENTRYPOINT 搭配指定 ENTRYPOINT 的默认参数)

ENTRYPOINT

与 CMD 类似,ENTRYPOINT 不会被 docker run 中指定的命令覆盖,如果想覆盖 ENTRYPOINT,则需要在 docker run 中指定 --entrypoint 选项。
它有两种模式:

ENTRYPOINT <command> (shell模式)
ENTRYPOINT ["executable", "param1", "param2"] (exec模式)

ADD 和 COPY

作用都是将文件或目录复制到 Dockerfile 构建的镜像中

ADD <src> <dest>
ADD ["<src>" "<dest>"] (适用于文件路径包含空格的情况)

COPY <src> <dest>
ADD ["<src>" "<dest>"] (适用于文件路径包含空格的情况)

ADD 包含了类似 tar 的解压功能,如果只是单纯复制文件或目录,建议使用 COPY,而且两者的源文件路径都使用 Dockerfile 相对路径,目标路径使用绝对路径。

COPY index.html /www/wwwroot

VOLUME

用于向容器添加卷,可以提供共享存储等功能,与 docker run -v 类似,但通过 VOLUME 指令创建的挂载点,无法指定主机上对应的目录,是自动生成的。

VOLUME ['/data']
VOLUME ["/data1","/data2"]

上面通过 VOLUME 指令指定了两个挂载点 /data1/data2,通过 docker inspect 可以查看详细信息。

WORKDIR

在容器内部设置工作目录,这样 ENTRYPOINT 和 CMD 指定的命令都会在容器中这个目录下进行。

WORKDIR /path/to/workdir

ENV

用于设置环境变量

ENV <KEY> <VALUE>
ENV <KEY>=<VALUE>

USER

用于指定镜像默认以什么用户去运行,后续的 RUN 也会使用指定用户,要临时获取管理员权限可以使用 gosu ,而不推荐 sudo

USER nginx

镜像就会以 nginx 身份运行,可以使用 uid,gid 等各种组合使用

ONBUILD

为镜像创建触发器,当一个镜像被用作其他镜像的基础镜像时,这个触发器会被执行,当子镜像被构建时会插入触发器中的指令。

ONBUILD COPY index.html /www/wwwroot

Dockerfile 的构建过程

  1. docker 会从 Dockerfile 文件头 FROM 指定的基础镜像运行一个容器
  2. 然后执行一条指令,对容器修改
  3. 接着执行类似 docker commit 的操作,创建新的镜像层
  4. 在基于刚创建的镜像运行一个新的容器
  5. 执行 Dockerfile 下一条指令,直到所有指令执行完毕

docker 会删除中间层创建的容器,但不会删除中间层镜像,所以可以使用 docker run 一个中间层容器,从而查看每一步构建后的镜像状态,这样就可以进行调试。

构建缓存

docker 在构建过程中会将之前构建的镜像看做缓存。

当第一次构建的时候,构建过程会比较慢,而在此进行相同的构建的时候,会看见 using cache 字样,表示使用了缓存,构建过程也非常快。

如果不想使用构建缓存,则在 docker build 中使用 —no-cache 选项。

还可以在 Dockerfile 中使用 ENV REFRESH_DATE 2021-01-01 来制定缓存刷新时间,更改这个时间,就会让后面的命令不使用缓存。

查看镜像的构建过程

docker history [image]

参考文章:Dockerfile详解


Never give up your dreams.