编写 Dockerfile

Docker 使用 Dockerfile 来描述构建步骤。我们将介绍什么是 Dockerfile,它能够做到的事情以及 Dockerfile 的一些基本语法,并且总结了最佳实践和注意事项。

Dockerfile 简介

Dockerfile 是由一系列命令和参数构成的脚本,这些命令应用于基础镜像并最终创建一个新的镜像。它们简化了从头到尾的流程并极大的简化了部署工作。Dockerfile 从 FROM 命令开始,紧接着跟随者各种方法,命令和参数。其产出为一个新的可以用于创建容器的镜像。

Dockerfile 的语法规则

Dockerfile 包含创建镜像所需要的全部指令。基于在 Dockerfile 中的指令,我们可以使用 Docker build  命令来创建镜像。通过减少镜像和容器的创建过程来简化部署。

Dockerfile 支持支持的语法命令如下:

INSTRUCTION argument 

指令不区分大小写。但是,命名约定为全部大写。

所有 Dockerfile 都必须以 FROM 命令开始。FROM 命令会指定镜像基于哪个基础镜像创建,接下来的命令也会基于这个基础镜像(注:CentOS 和 Ubuntu 有些命令可是不一样的)。FROM 命令可以多次使用,表示会创建多个镜像。具体语法如下:

FROM <image name>

例如:

FROM ubuntu

上面的指定告诉我们,新的镜像将基于 Ubuntu 的镜像来构建。

继 FROM 命令,DockefFile 还提供了一些其它的命令以实现自动化。在文本文件或 Dockerfile 文件中这些命令的顺序就是它们被执行的顺序。

让我们了解一下这些有趣的 Dockerfile 命令吧。

  • MAINTAINER:设置该镜像的作者。语法如下:

    MAINTAINER <author name> 
  • RUN:在 shell 或者 exec 的环境下执行的命令。RUN指令会在新创建的镜像上添加新的层面,接下来提交的结果用在Dockerfile的下一条指令中。语法如下:

    RUN <command> 
  • ADD:复制文件指令。它有两个参数 source 和 destination。destination 是容器内的路径。source 可以是 URL 或者是启动配置上下文中的一个文件。语法如下:

    ADD <source> <destination> 
  • CMD:提供了容器默认的执行命令。 Dockerfile 只允许使用一次 CMD 指令。 使用多个 CMD 会抵消之前所有的指令,只有最后一个指令生效。 CMD 有三种形式:

    CMD ["executable","param1","param2"]
    CMD ["param1","param2"]
    CMD command param1 param2 
  • EXPOSE:指定容器在运行时监听的端口。语法如下:

    EXPOSE <port>
  • ENTRYPOINT:配置给容器一个可执行的命令,这意味着在每次使用镜像创建容器时一个特定的应用程序可以被设置为默认程序。同时也意味着该镜像每次被调用时仅能运行指定的应用。类似于CMD,Docker只允许一个ENTRYPOINT,多个ENTRYPOINT会抵消之前所有的指令,只执行最后的ENTRYPOINT指令。语法如下:

    ENTRYPOINT ["executable", "param1","param2"]
    ENTRYPOINT command param1 param2 
  • WORKDIR:指定RUNCMDENTRYPOINT 命令的工作目录。语法如下:

    WORKDIR /path/to/workdir 
  • ENV:设置环境变量。它们使用键值对,增加运行程序的灵活性。语法如下:

    ENV <key> <value> 
  • USER:镜像正在运行时设置一个 UID。语法如下:

    USER <uid> 
  • VOLUME:授权访问从容器内到主机上的目录。语法如下:

    VOLUME ["/data"] 

Dockerfile最佳实践

与使用的其他任何应用程序一样,总会有可以遵循的最佳实践。你可以阅读更多有关 Dockerfile 的最佳实践。以下是我们列出的基本的 Dockerfile 最佳实践:

  • 保持常见的指令像 MAINTAINER 以及从上至下更新 Dockerfile 命令。
  • 当构建镜像时使用可理解的标签,以便更好地管理镜像。
  • 避免在 Dockerfile 中映射公有端口。
  • CMD 与 ENTRYPOINT 命令请使用数组语法。

DaoCloud 上的 Dockerfile 编写注意事项

DaoCloud 通过读取 Dockerfile 内容,和来自代码仓库的源代码,为用户构建 Docker 镜像。由于众所周知的原因,国内访问 Docker Hub 的速度令人无法忍受,因此国内常规网络环境下的 Docker 镜像构建速度非常缓慢。DaoCloud 采用非常先进的全球分布式构建引擎,有效缓缓解国内网络问题带来的构建延迟。DaoCloud 兼容 Dockerfile 的所有格式,但是有以下几个注意事项,需要开发者知晓:

  • 如您在 Dockerfile 中需要更新 Linux 组件,或安装编程语言的依赖包等,请不要使用国内源,请使用您的 Linux 发行版和编程语言分发机制提供的默认更新源。
  • 您可以在构建过程中看到完整的日志文件,如果构建出现问题,日志文件是排错的首选方式。
  • 考虑到您的镜像会频繁构建,我们在构建服务器端开启了缓存,之前构建过的 Docker Image Layer 不会重新执行构建,完成和传输的速度也会更快。
  • 我们设定了一个构建超时的时间。对于免费用户,构建时间上限是 1 小时,如果 1 小时内您的镜像构建仍未完成(通常是遇到构建问题并死锁),系统将取消您的构建任务;对于付费用户,这个超时时限是 3 小时。

Docker 入门教程

我们推荐 Flux7 的 Docker 入门教程,国内社区已有翻译,建议大家阅读学习。

本文及上述推荐文章的译者是田浩浩,他是悉尼大学(USYD)硕士研究生,目前在珠海从事 Android 应用开发工作。业余时间专注 Docker 的学习与研究。田浩浩已授权 DaoCloud 使用这些内容。