Dockerfile最佳实践(一)
2016-10-25 12:02
225 查看
【编者的话】本文是Docker入门教程第三章-DockerFile的进阶篇,作者主要介绍了缓存、标签、端口以及CMD与ENTRYPOINT的最佳用法,并通过案例分析了注意事项,比如我们应该使用常用且不变的Dockerfile开头、通过
Dockerfile使用简单的语法来构建镜像。下面是一些建议和技巧以帮助你使用Dockerfile。
为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。我所有的Dockerfile的前五行都是这样的:
更改
所以,我们应该使用常用且不变的Dockerfile开始(译者注:上面的例子)指令来利用缓存。
注意,始终通过
如果镜像的使用者关心容器公有映射了哪个公有端口,他们可以在运行镜像时通过
切勿在Dockerfile映射公有端口。
这看起来好像没什么问题,但仔细一看其实两种方式差距很大。如果你使用第二个语法:
如果你不知道Docker修改了
使用CMD和ENTRYPOINT时,请务必使用数组语法。
这是Docker化Rethinkdb的所有配置文件。在开始我们有标准的5行来确保基础镜像是最新的、端口的公开等。当
在Dockerfile中我还设置了一个默认
输出
现在,让我们带上
输出
就这样,一个全面的可以访问db和管理控制台的Rethinkdb实例就运行起来了,你可以用与镜像交互一样的方式来与其交互。虽然简单小巧但它的功能非常强大。
CMD和ENTRYPOINT 结合在一起使用更好。
我希望这篇文章可以帮助你使用Dockerfiles以及构建镜像。Dockerfile是Docker的重要一部分,无论你是构建或是使用镜像,它都非常简单而且使用方便。我打算投入更多的时间来提供一个完整的、功能强大但简单的解决方案来使用Dockerfile构建Docker镜像。
原文链接:Dockerfile Best Practices - take 1 (翻译:田浩浩 校对:李颖杰)
===========================
译者介绍
田浩浩,悉尼大学USYD硕士研究生,目前在珠海从事Android应用开发工作。业余时间专注Docker的学习与研究,希望通过DockerOne把最新最优秀的译文贡献给大家,与读者一起畅游Docker的海洋。
-t标记来构建镜像、勿在Dockerfile映射公有端口等等。
Dockerfile使用简单的语法来构建镜像。下面是一些建议和技巧以帮助你使用Dockerfile。
1、使用缓存
Dockerfile的每条指令都会将结果提交为新的镜像,下一个指令将会基于上一步指令的镜像的基础上构建,如果一个镜像存在相同的父镜像和指令(除了ADD),Docker将会使用镜像而不是执行该指令,即缓存。
为了有效地利用缓存,你需要保持你的Dockerfile一致,并且尽量在末尾修改。我所有的Dockerfile的前五行都是这样的:
FROM ubuntu MAINTAINER Michael Crosby <michael@crosbymichael.com> RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list RUN apt-get update RUN apt-get upgrade -y
更改
MAINTAINER指令会使Docker强制执行
RUN指令来更新apt,而不是使用缓存。
所以,我们应该使用常用且不变的Dockerfile开始(译者注:上面的例子)指令来利用缓存。
2、使用标签
除非你正在用Docker做实验,否则你应当通过-t选项来
docker build新的镜像以便于标记构建的镜像。一个简单的可读标签将帮助你管理每个创建的镜像。
docker build -t="crosbymichael/sentry" .
注意,始终通过
-t标记来构建镜像。
3、公开端口
两个Docker的核心概念是可重复和可移植。镜像应该可以运行在任何主机上并且运行尽可能多的次数。在Dockerfile中你有能力映射私有和公有端口,但是你永远不要通过Dockerfile映射公有端口。通过映射公有端口到主机上,你将只能运行一个容器化应用程序实例。(译者注:运行多个端口不就冲突啦)#private and public mapping EXPOSE 80:8080 #private only EXPOSE 80
如果镜像的使用者关心容器公有映射了哪个公有端口,他们可以在运行镜像时通过
-p参数设置,否则,Docker会自动为容器分配端口。
切勿在Dockerfile映射公有端口。
4、CMD与ENTRYPOINT的语法
CMD和
ENTRYPOINT指令都非常简单,但它们都有一个隐藏的容易出错的“功能”,如果你不知道的话可能会在这里踩坑,这些指令支持两种不同的语法。
CMD /bin/echo #or CMD ["/bin/echo"]
这看起来好像没什么问题,但仔细一看其实两种方式差距很大。如果你使用第二个语法:
CMD(或
ENTRYPOINT)是一个数组,它执行的命令完全像你期望的那样。如果使用第一种语法,Docker会在你的命令前面加上
/bin/sh -c,我记得一直都是这样。
如果你不知道Docker修改了
CMD命令,在命令前加上
/bin/sh -c可能会导致一些意想不到的问题以及难以理解的功能。因此,在使用这两个指令时你应当使用数组语法,因为数组语法会确切地执行你打算执行的命令。
使用CMD和ENTRYPOINT时,请务必使用数组语法。
5、CMD和ENTRYPOINT 结合使用更好
docker run命令中的参数都会传递给
ENTRYPOINT指令,而不用担心它被覆盖(跟
CMD不同)。当与
CMD一起使用时
ENTRYPOINT的表现会更好。让我们来研究一下我的Rethinkdb Dockerfile,看看如何使用它。
#Dockerfile for Rethinkdb #http://www.rethinkdb.com/ FROM ubuntu MAINTAINER Michael Crosby <michael@crosbymichael.com> RUN echo "deb http://archive.ubuntu.com/ubuntu precise main universe" > /etc/apt/sources.list RUN apt-get update RUN apt-get upgrade -y RUN apt-get install -y python-software-properties RUN add-apt-repository ppa:rethinkdb/ppa RUN apt-get update RUN apt-get install -y rethinkdb #Rethinkdb process EXPOSE 28015 #Rethinkdb admin console EXPOSE 8080 #Create the /rethinkdb_data dir structure RUN /usr/bin/rethinkdb create ENTRYPOINT ["/usr/bin/rethinkdb"] CMD ["--help"]
这是Docker化Rethinkdb的所有配置文件。在开始我们有标准的5行来确保基础镜像是最新的、端口的公开等。当
ENTRYPOINT指令出现时,我们知道每次运行该镜像,在
docker run过程中传递的所有参数将成为
ENTRYPOINT(
/usr/bin/rethinkdb)的参数。
在Dockerfile中我还设置了一个默认
CMD参数
--help。这样做是为了
docker run期间如果没有参数的传递,rethinkdb将会给用户显示默认的帮助文档。这是你所期望的与rethinkdb交互相同的功能。
docker run crosbymichael/rethinkdb
输出
Running 'rethinkdb' will create a new data directory or use an existing one, and serve as a RethinkDB cluster node. File path options: -d [ --directory ] path specify directory to store data and metadata --io-threads n how many simultaneous I/O operations can happen at the same time Machine name options: -n [ --machine-name ] arg the name for this machine (as will appear in the metadata). If not specified, it will be randomly chosen from a short list of names. Network options: --bind {all | addr} add the address of a local interface to listen on when accepting connections; loopback addresses are enabled by default --cluster-port port port for receiving connections from other nodes --driver-port port port for rethinkdb protocol client drivers -o [ --port-offset ] offset all ports used locally will have this value added -j [ --join ] host:port host and port of a rethinkdb node to connect to .................
现在,让我们带上
--bind all参数来运行容器。
docker run crosbymichael/rethinkdb --bind all
输出
info: Running rethinkdb 1.7.1-0ubuntu1~precise (GCC 4.6.3)... info: Running on Linux 3.2.0-45-virtual x86_64 info: Loading data from directory /rethinkdb_data warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems. warn: Could not turn off filesystem caching for database file: "/rethinkdb_data/auth_metadata" (Is the file located on a filesystem that doesn't support direct I/O (e.g. some encrypted or journaled file systems)?) This can cause performance problems. info: Listening for intracluster connections on port 29015 info: Listening for client driver connections on port 28015 info: Listening for administrative HTTP connections on port 8080 info: Listening on addresses: 127.0.0.1, 172.16.42.13 info: Server ready info: Someone asked for the nonwhitelisted file /js/handlebars.runtime-1.0.0.beta.6.js, if this should be accessible add it to the whitelist.
就这样,一个全面的可以访问db和管理控制台的Rethinkdb实例就运行起来了,你可以用与镜像交互一样的方式来与其交互。虽然简单小巧但它的功能非常强大。
CMD和ENTRYPOINT 结合在一起使用更好。
我希望这篇文章可以帮助你使用Dockerfiles以及构建镜像。Dockerfile是Docker的重要一部分,无论你是构建或是使用镜像,它都非常简单而且使用方便。我打算投入更多的时间来提供一个完整的、功能强大但简单的解决方案来使用Dockerfile构建Docker镜像。
原文链接:Dockerfile Best Practices - take 1 (翻译:田浩浩 校对:李颖杰)
===========================
译者介绍
田浩浩,悉尼大学USYD硕士研究生,目前在珠海从事Android应用开发工作。业余时间专注Docker的学习与研究,希望通过DockerOne把最新最优秀的译文贡献给大家,与读者一起畅游Docker的海洋。
相关文章推荐
- Dockerfile 最佳实践
- Dockerfile 最佳实践
- Dockerfile最佳实践总结
- 英国电信设计模式最佳实践
- 超实用的JavaScript技巧及最佳实践(上)
- 最佳实践之JS-状态模式
- Android 6.0 运行时权限管理最佳实践
- 最重要的 Java EE 最佳实践
- Cognos 云最佳实践: 调整架构提供性能和可伸缩性
- Maven最佳实践:划分模块
- jquery性能最佳实践
- Web 前端优化最佳实践之 图象篇
- 强烈推荐C++编程规范:101条规则、准则与最佳实践
- PHP核心技术与最佳实践学习(一)面向对象
- 分布式消息队列RocketMQ--事务消息--解决分布式事务的最佳实践
- Android开发:Translucent System Bar 的最佳实践(沉浸式)
- SeaJS 里版本号和时间戳管理的最佳实践
- 前端代码标准最佳实践:javascript篇
- MySQL性能优化的21个最佳实践 和 mysql使用索引
- 卡片式设计的最佳实践分享