先回顾一下通过 Dockerfile 构建镜像的过程:

  • 从 base 镜像运行一个容器。
  • 执行一条指令,对容器做修改。
  • 执行类似 docker commit 的操作,生成一个新的镜像层。
  • Docker 再基于刚刚提交的镜像运行一个新容器。
  • 重复 2-4 步,直到 Dockerfile 中的所有指令执行完毕

一、调试 Dockerfile

包括 Dockerfile 在内的任何脚本和程序都会出错。有错并不可怕,但必须有办法排查;

来看一个调试的例子,Dockerfile 内容如下:

第一步:准备Dockerfile文件

docker启动一个images 启动dockerfile_Dockerfile

第二步:执行docker build命令:

命令如下所示:

docker build -t image-debug .

具体结果如下所示: 

docker启动一个images 启动dockerfile_docker启动一个images_02

 可以看到,Dockerfile 在执行第三步 RUN 指令时失败,我们可以利用第二步创建的镜像 be460bb201e1进行调试,方式是通过 docker run -it 启动镜像的一个容器;

命令如下所示:

docker run -it  be460bb201e1

具体结果如下所示:

二、Dockerfile常用指令

FROM  指定 base 镜像

MAINTAINER 设置镜像的作者,可以是任意字符串

COPY 将文件从 build context 复制到镜像,注意COPY 支持两种形式:COPY src dest或者COPY ["src", "dest"]

注意:src 只能指定 build context 中的文件或目录。

ADD 与 COPY 类似,从 build context 复制文件到镜像;

ENV 设置环境变量,环境变量可被后面的指令使用;

EXPOSE指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来;

VOLUME将文件或目录声明为 volume

WORKDIR为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录

RUN在容器中运行指定的命令

CMD容器启动时运行指定的命令,Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效;

ENTRYPOINT设置容器启动时运行的命令。Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效;

再举一个例子来练习一下Dockerfile:

第一步,准备Dockerfile文件

docker启动一个images 启动dockerfile_Dockerfile_03

第二步:执行命令:

docker build -t my-image .

具体结果如下:

docker启动一个images 启动dockerfile_Dockerfile_04

说明:build context说白了,就是Dockerfile所在的目录以及子目录;

最佳实践

RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包;

CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换;

ENTRYPOINT 配置容器启动时运行的命令