Docker 快速入门之 Dockerfile

Docker 快速入门之 Dockerfile

在之前的文章中我们提到可以通过容器创建一个我们自定义过的镜像,那么我们是否可以直接通过基础的镜像直接自定义镜像呢?答案当然是可以的,在 Docker 中我们可以从名为 Dockerfile 的文件中读取指令并且自动构建镜像。在本文中,将介绍 Dockerfile 的基本语法以及基本知识。

1、Dockerfile 是什么?

Dockerfile 其实是一份文本文档,里面包含了用户可以用来操作镜像的一些指令。通过顺序执行这些指令,最后得到一个自定义的镜像,这有点类似于我们的 shell 脚本。

2、Dockerfile 示例

接下来先看一个 Dockerfile 示例:

  1. <span class="pln">FROM CentOS</span>
  2. <span class="pln">LABEL maintainer</span><span class="pun">=</span><span class="str">"Locez <[email protected]>"</span>
  3. <span class="pln">ENV TEST</span><span class="pun">=</span><span class="str">"This is a test env"</span>
  4. <span class="pln">COPY nginx</span><span class="pun">.</span><span class="pln">repo </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="kwd">yum</span><span class="pun">.</span><span class="pln">repos</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">repo</span>
  5. <span class="pln">RUN </span><span class="kwd">yum</span><span class="pln"> update </span><span class="pun">-</span><span class="pln">y </span><span class="pun">&&</span><span class="pln"> \</span>
  6. <span class="kwd">yum</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y nginx</span>
  7. <span class="pln">COPY nginx</span><span class="pun">.</span><span class="pln">conf </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf</span>
  8. <span class="pln">COPY index</span><span class="pun">.</span><span class="pln">html </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">share</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">index</span><span class="pun">.</span><span class="pln">html</span>
  9. <span class="pln">COPY index_files</span><span class="str">/ /</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">share</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">index_files</span><span class="pun">/</span>
  10. <span class="pln">EXPOSE </span><span class="lit">80</span>
  11. <span class="pln">CMD </span><span class="pun">[</span><span class="str">"/usr/sbin/nginx"</span><span class="pun">,</span><span class="str">"-g"</span><span class="pun">,</span><span class="str">"daemon off;"</span><span class="pun">]</span>

在上面我们可以看到 Dockerfile 中的一些指令,通过名称我们也可以猜到这些指令大概是干嘛的,其中有一些对文件的操作,因此我们先来看看用于存放 Dockerfile 的这个目录的目录结构:

  1. <span class="com">#</span><span class="pln"> tree </span><span class="pun">.</span>
  2. <span class="pun">.</span>
  3. <span class="pun">├──</span><span class="typ">Dockerfile</span>
  4. <span class="pun">├──</span><span class="pln"> index_files</span>
  5. <span class="pun">│</span><span class="pun">├──</span><span class="lit">145049z4og8xyjhx4xy8go</span><span class="pun">.</span><span class="pln">jpg</span>
  6. <span class="pun">│</span><span class="pun">├──</span><span class="lit">222746e5vh38d7ey3leyps</span><span class="pun">.</span><span class="pln">jpg</span>
  7. <span class="pun">│</span><span class="pun">├──</span><span class="lit">88x31.png</span>
  8. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> archlinux</span><span class="pun">-</span><span class="pln">splash</span><span class="pun">.</span><span class="pln">png</span>
  9. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> bdshare</span><span class="pun">.</span><span class="pln">css</span>
  10. <span class="pun">│</span><span class="pun">├──</span><span class="typ">Best</span><span class="pun">-</span><span class="typ">Linux</span><span class="pun">-</span><span class="typ">Markdown</span><span class="pun">-</span><span class="typ">Editors</span><span class="pun">.</span><span class="pln">png</span>
  11. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> core</span><span class="pun">.</span><span class="pln">js</span>
  12. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> docker</span><span class="pun">-</span><span class="pln">icon</span><span class="pun">.</span><span class="pln">jpg</span>
  13. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> Hadoop</span><span class="pun">-</span><span class="pln">pic1</span><span class="pun">.</span><span class="pln">png</span>
  14. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> jquery_002</span><span class="pun">.</span><span class="pln">js</span>
  15. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> jquery</span><span class="pun">.</span><span class="pln">css</span>
  16. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> jquery</span><span class="pun">.</span><span class="pln">js</span>
  17. <span class="pun">│</span><span class="pun">├──</span><span class="typ">MathJax</span><span class="pun">.</span><span class="pln">js</span>
  18. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> pic</span><span class="pun">.</span><span class="pln">gif</span>
  19. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> raspberrypiraspberry</span><span class="pun">-</span><span class="pln">pi</span><span class="pun">-</span><span class="pln">logo</span><span class="pun">.</span><span class="pln">jpg</span>
  20. <span class="pun">│</span><span class="pun">├──</span><span class="kwd">script</span><span class="pun">.</span><span class="pln">js</span>
  21. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> scrollup</span><span class="pun">.</span><span class="pln">png</span>
  22. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> share</span><span class="pun">.</span><span class="pln">js</span>
  23. <span class="pun">│</span><span class="pun">├──</span><span class="pln"> style</span><span class="pun">.</span><span class="pln">css</span>
  24. <span class="pun">│</span><span class="pun">└──</span><span class="pln"> z_stat</span><span class="pun">.</span><span class="pln">js</span>
  25. <span class="pun">├──</span><span class="pln"> index</span><span class="pun">.</span><span class="pln">html</span>
  26. <span class="pun">├──</span><span class="pln"> nginx</span><span class="pun">.</span><span class="pln">conf</span>
  27. <span class="pun">└──</span><span class="pln"> nginx</span><span class="pun">.</span><span class="pln">repo</span>
  28. <span class="lit">1</span><span class="pln"> directory</span><span class="pun">,</span><span class="lit">24</span><span class="pln"> files</span>

构建镜像

在当前目录下执行以下命令构建镜像:

  1. <span class="com">#</span><span class="pln"> docker build </span><span class="pun">-</span><span class="pln">t locez</span><span class="pun">/</span><span class="pln">nginx </span><span class="pun">.</span>
  2. <span class="typ">Sending</span><span class="pln"> build context to </span><span class="typ">Docker</span><span class="pln"> daemon </span><span class="lit">1.851</span><span class="pln"> MB</span>
  3. <span class="typ">Step</span><span class="lit">1</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> FROM centos</span>
  4. <span class="pun">---></span><span class="lit">196e0ce0c9fb</span>
  5. <span class="typ">Step</span><span class="lit">2</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> LABEL maintainer </span><span class="str">"Locez <[email protected]>"</span>
  6. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  7. <span class="pun">---></span><span class="lit">9bba3042bcdb</span>
  8. <span class="typ">Step</span><span class="lit">3</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> ENV TEST </span><span class="str">"This is a test env"</span>
  9. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  10. <span class="pun">---></span><span class="pln"> c0ffe95ea0c5</span>
  11. <span class="typ">Step</span><span class="lit">4</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> COPY nginx</span><span class="pun">.</span><span class="pln">repo </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="kwd">yum</span><span class="pun">.</span><span class="pln">repos</span><span class="pun">.</span><span class="pln">d</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">repo</span>
  12. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  13. <span class="pun">---></span><span class="pln"> bb6ee4c30d56</span>
  14. <span class="typ">Step</span><span class="lit">5</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> RUN </span><span class="kwd">yum</span><span class="pln"> update </span><span class="pun">-</span><span class="pln">y </span><span class="pun">&&</span><span class="kwd">yum</span><span class="pln"> install </span><span class="pun">-</span><span class="pln">y nginx</span>
  15. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  16. <span class="pun">---></span><span class="lit">6d46b41099c3</span>
  17. <span class="typ">Step</span><span class="lit">6</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> COPY nginx</span><span class="pun">.</span><span class="pln">conf </span><span class="pun">/</span><span class="pln">etc</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">.</span><span class="pln">conf</span>
  18. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  19. <span class="pun">---></span><span class="pln"> cfe908390aae</span>
  20. <span class="typ">Step</span><span class="lit">7</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> COPY index</span><span class="pun">.</span><span class="pln">html </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">share</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">index</span><span class="pun">.</span><span class="pln">html</span>
  21. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  22. <span class="pun">---></span><span class="lit">21729476079d</span>
  23. <span class="typ">Step</span><span class="lit">8</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> COPY index_files</span><span class="str">/ /</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">share</span><span class="pun">/</span><span class="pln">nginx</span><span class="pun">/</span><span class="pln">html</span><span class="pun">/</span><span class="pln">index_files</span><span class="pun">/</span>
  24. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  25. <span class="pun">---></span><span class="lit">662f06ec7b46</span>
  26. <span class="typ">Step</span><span class="lit">9</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> EXPOSE </span><span class="lit">80</span>
  27. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  28. <span class="pun">---></span><span class="lit">30db5a889d0a</span>
  29. <span class="typ">Step</span><span class="lit">10</span><span class="pun">/</span><span class="lit">10</span><span class="pun">:</span><span class="pln"> CMD </span><span class="pun">/</span><span class="pln">usr</span><span class="pun">/</span><span class="pln">sbin</span><span class="pun">/</span><span class="pln">nginx </span><span class="pun">-</span><span class="pln">g daemon off</span><span class="pun">;</span>
  30. <span class="pun">---></span><span class="typ">Using</span><span class="pln"> cache</span>
  31. <span class="pun">---></span><span class="pln"> d29b9d4036d2</span>
  32. <span class="typ">Successfully</span><span class="pln"> built d29b9d4036d2</span>

然后用该镜像启动容器:

  1. <span class="com">#</span><span class="pln"> docker run </span><span class="pun">-</span><span class="pln">d </span><span class="pun">-</span><span class="pln">it </span><span class="pun">--</span><span class="kwd">rm</span><span class="pun">--</span><span class="pln">name </span><span class="kwd">test</span><span class="pun">-</span><span class="pln">nginx </span><span class="pun">-</span><span class="pln">p </span><span class="lit">8080</span><span class="pun">:</span><span class="lit">80</span><span class="pln"> locez</span><span class="pun">/</span><span class="pln">nginx</span>
  2. <span class="pln">e06fd991ca1b202e08cf1578f8046355fcbba10dd9a90e11d43282f3a1e36d29</span>

用浏览器访问 http://localhost:8080/ 即可看到部署的内容。

3 Dockerfile 指令解释

Dockerfile 支持 FROM、 RUN、 CMD、 LABEL、 EXPOSE、 ENV、 ADD、 COPY、 ENTRYPOINT、 VOLUME、 USER、 WORKDIR、 ARG、 ONBUILD、 SHELL 等指令,这里只选择常用的几个进行讲解,可结合上面的示例进行理解。其它的请自行查阅官方文档。

3.1 FROM

FROM 指令用于指定要操作的基础镜像,因为在我们构建我们自己的镜像的时候需要一个基础镜像。 语法:

  1. <span class="pln">FROM </span><span class="pun"><</span><span class="pln">image</span><span class="pun">></span><span class="pun">[</span><span class="pln">AS </span><span class="pun"><</span><span class="pln">name</span><span class="pun">>]</span>
  2. <span class="pln">FROM </span><span class="pun"><</span><span class="pln">image</span><span class="pun">>[:<</span><span class="pln">tag</span><span class="pun">>]</span><span class="pun">[</span><span class="pln">AS </span><span class="pun"><</span><span class="pln">name</span><span class="pun">>]</span>

其中 [AS <name>] 为指定一个名称,在一个 Dockerfile 中多次使用 FROM 时如有需要,可用 COPY --from=<name|index> 语法进行复制。

3.2 RUN

RUN 指令用于执行命令,并且是在新的一层上执行,并把执行后的结果提交,也就是生成新的一层。基于这个问题,我们在使用 RUN 指令时应该尽可能的把要执行的命令一次写完,以减少最后生成的镜像的层数。 语法:

  1. <span class="pln">RUN </span><span class="pun"><</span><span class="pln">command</span><span class="pun">></span>
  2. <span class="pln">RUN </span><span class="pun">[</span><span class="str">"executable"</span><span class="pun">,</span><span class="str">"param1"</span><span class="pun">,</span><span class="str">"param2"</span><span class="pun">]</span>

3.3 CMD

CMD 指令用于给容器启动时指定一个用于执行的命令,例如上例中的 nginx 启动命令。 语法:

  1. <span class="pln">CMD </span><span class="pun">[</span><span class="str">"executable"</span><span class="pun">,</span><span class="str">"param1"</span><span class="pun">,</span><span class="str">"param2"</span><span class="pun">]</span>
  2. <span class="pln">CMD </span><span class="pun">[</span><span class="str">"param1"</span><span class="pun">,</span><span class="str">"param2"</span><span class="pun">]</span><span class="com">### 用于给 ENTRYPOINT 指令提供默认参数</span>
  3. <span class="pln">CMD command param1 param2</span>

3.4 LABEL

LABEL 指令用于为镜像指定标签,可用 docker inspect 命令查看。可用来代替被舍弃的 MAINTAINER 命令。 语法:

  1. <span class="pln">LABEL </span><span class="pun"><</span><span class="pln">key</span><span class="pun">>=<</span><span class="pln">value</span><span class="pun">></span><span class="pun"><</span><span class="pln">key</span><span class="pun">>=<</span><span class="pln">value</span><span class="pun">></span><span class="pun"><</span><span class="pln">key</span><span class="pun">>=<</span><span class="pln">value</span><span class="pun">></span><span class="pun">...</span>

3.5 EXPOSE

EXPOSE 指令用于告诉 Docker 容器监听的特殊端口,但是此时端口还没有暴露给 host ,只有当在运行一个容器显式用参数 -p 或者 -p 的时候才会暴露端口。 语法:

  1. <span class="pln">EXPOSE </span><span class="pun"><</span><span class="pln">port</span><span class="pun">></span><span class="pun">[<</span><span class="pln">port</span><span class="pun">>/<</span><span class="pln">protocol</span><span class="pun">>...]</span>

3.6 ENV

ENV 指令用于设定环境变量。 语法:

  1. <span class="pln">ENV </span><span class="pun"><</span><span class="pln">key</span><span class="pun">></span><span class="pun"><</span><span class="pln">value</span><span class="pun">></span>
  2. <span class="pln">ENV </span><span class="pun"><</span><span class="pln">key</span><span class="pun">>=<</span><span class="pln">value</span><span class="pun">></span><span class="pun">...</span>

3.7 ADD

ADD 指令用于复制新文件,目录,远程文件到容器中。其中 <src> 可以为文件,目录,URL,若为可解压文件,在复制后会解压。 语法:

  1. <span class="pln">ADD </span><span class="pun"><</span><span class="pln">src</span><span class="pun">>...</span><span class="pun"><</span><span class="pln">dest</span><span class="pun">></span>
  2. <span class="pln">ADD </span><span class="pun">[</span><span class="str">"<src>"</span><span class="pun">,...</span><span class="str">"<dest>"</span><span class="pun">]</span>

3.8 COPY

COPY 指令与 ADD 指令非常相似,但 COPY 比较直观且简单,它只支持本地的文件以及目录的复制,不像 ADD 指令可以远程获取文件并解压。 语法:

  1. <span class="pln">COPY </span><span class="pun"><</span><span class="pln">src</span><span class="pun">>...</span><span class="pun"><</span><span class="pln">dest</span><span class="pun">></span>
  2. <span class="pln">COPY </span><span class="pun">[</span><span class="str">"<src>"</span><span class="pun">,...</span><span class="str">"<dest>"</span><span class="pun">]</span>

3.9 ENTRYPOINT

ENTRYPOINT 指令也跟 CMD 指令相似,用于指定容器启动时执行的命令。当使用 ENTRYPOINT 指令时,可用 CMD 命令配合,这样在启动容器时,可以对 CMD 指令写入的参数进行覆盖。 语法:

  1. <span class="pln">ENTRYPOINT </span><span class="pun">[</span><span class="str">"executable"</span><span class="pun">,</span><span class="str">"param1"</span><span class="pun">,</span><span class="str">"param2"</span><span class="pun">]</span>

例子:

  1. <span class="pln">ENTRYPOINT </span><span class="pun">[</span><span class="str">"top"</span><span class="pun">,</span><span class="str">"-b"</span><span class="pun">]</span>
  2. <span class="pln">CMD </span><span class="pun">[</span><span class="str">"-c"</span><span class="pun">]</span>

上面的 -c 参数可以在启动时覆盖 docker run -it --rm --name test top -H。 如果要覆盖 ENTRYPOINT 指令则用 --entrypoint 参数启动容器。

3.10 VOLUME

VOLUME 指令用于为容器创建一个挂载点,这个挂载点可以用来挂载 本地文件/文件夹 也可以用来挂载 数据卷。其中若在启动一个新容器时没有指定挂载目录,则会自动创建一个数据卷,当容器被销毁时,数据卷如果没有被其它容器引用则会被删除。 语法:

  1. <span class="pln">VOLUME </span><span class="pun">[</span><span class="str">"/data1"</span><span class="pun">,</span><span class="str">"/data2"</span><span class="pun">]</span>

3.11 USER

USER 指令用于设置执行 RUN, CMD, ENTRYPOINT 等指令的用户以及用户组。默认为 root 用户。 语法:

  1. <span class="pln">USER </span><span class="pun"><</span><span class="pln">user</span><span class="pun">>[:<</span><span class="pln">group</span><span class="pun">>]</span>

3.12 WORKDIR

WORKDIR 指令用于设置 RUN, CMD, ENTRYPOINT, COPY, ADD 等指令的工作目录。 语法:

  1. <span class="pln">WORKDIR </span><span class="pun">/</span><span class="pln">path</span><span class="pun">/</span><span class="pln">to</span><span class="pun">/</span><span class="pln">workdir</span>

4 总结


本文从一个具体的例子出发,讲述了如何利用 Dockerfile 构建镜像,然后解释了 Dockerfile 文件中的指令的语法,有关更多内容可访问官方文档。

5 参考资料


更多Docker相关教程见以下内容: 

Docker 的详细介绍:请点这里
Docker 的下载地址:请点这里

相关推荐