Dockerfile使用简单的语法来构建镜像。下面是一些建议和技巧以帮助你使用Dockerfile。
Dockerfile的每条指令都会将结果提交为新的镜像,下一个指令将会基于上一步指令的镜像的基础上构建,如果一个镜像存在相同的父镜像和指令(除了<code>ADD</code>),Docker将会使用镜像而不是执行该指令,即缓存。
为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。我所有的Dockerfile的前五行都是这样的:
更改<code>MAINTAINER</code>指令会使Docker强制执行<code>RUN</code>指令来更新apt,而不是使用缓存。
所以,我们应该使用常用且不变的Dockerfile开始(译者注:上面的例子)指令来利用缓存。
除非你正在用Docker做实验,否则你应当通过<code>-t</code>选项来<code>docker build</code>新的镜像以便于标记构建的镜像。一个简单的可读标签将帮助你管理每个创建的镜像。
注意,始终通过<code>-t</code>标记来构建镜像。
两个Docker的核心概念是可重复和可移植。镜像应该可以运行在任何主机上并且运行尽可能多的次数。在Dockerfile中你有能力映射私有和公有端口,但是你永远不要通过Dockerfile映射公有端口。通过映射公有端口到主机上,你将只能运行一个容器化应用程序实例。(译者注:运行多个端口不就冲突啦)
如果镜像的使用者关心容器公有映射了哪个公有端口,他们可以在运行镜像时通过<code>-p</code>参数设置,否则,Docker会自动为容器分配端口。
切勿在Dockerfile映射公有端口。
<code>CMD</code>和<code>ENTRYPOINT</code>指令都非常简单,但它们都有一个隐藏的容易出错的“功能”,如果你不知道的话可能会在这里踩坑,这些指令支持两种不同的语法。
这看起来好像没什么问题,但仔细一看其实两种方式差距很大。如果你使用第二个语法:<code>CMD</code>(或<code>ENTRYPOINT</code>)是一个数组,它执行的命令完全像你期望的那样。如果使用第一种语法,Docker会在你的命令前面加上<code>/bin/sh -c</code>,我记得一直都是这样。
如果你不知道Docker修改了<code>CMD</code>命令,在命令前加上<code>/bin/sh -c</code>可能会导致一些意想不到的问题以及难以理解的功能。因此,在使用这两个指令时你应当使用数组语法,因为数组语法会确切地执行你打算执行的命令。
使用CMD和ENTRYPOINT时,请务必使用数组语法。
这是Docker化Rethinkdb的所有配置文件。在开始我们有标准的5行来确保基础镜像是最新的、端口的公开等。当<code>ENTRYPOINT</code>指令出现时,我们知道每次运行该镜像,在<code>docker run</code>过程中传递的所有参数将成为<code>ENTRYPOINT</code>(<code>/usr/bin/rethinkdb</code>)的参数。
在Dockerfile中我还设置了一个默认<code>CMD</code>参数<code>--help</code>。这样做是为了<code>docker run</code>期间如果没有参数的传递,rethinkdb将会给用户显示默认的帮助文档。这是你所期望的与rethinkdb交互相同的功能。
输出
现在,让我们带上<code>--bind all</code>参数来运行容器。
就这样,一个全面的可以访问db和管理控制台的Rethinkdb实例就运行起来了,你可以用与镜像交互一样的方式来与其交互。虽然简单小巧但它的功能非常强大。
CMD和ENTRYPOINT 结合在一起使用更好。
我希望这篇文章可以帮助你使用Dockerfiles以及构建镜像。Dockerfile是Docker的重要一部分,无论你是构建或是使用镜像,它都非常简单而且使用方便。我打算投入更多的时间来提供一个完整的、功能强大但简单的解决方案来使用Dockerfile构建Docker镜像。
本文转自 h2appy 51CTO博客,原文链接:http://blog.51cto.com/h2appy/1865358,如需转载请自行联系原作者