文档章节

高效编写Dockerfile的几条准则

CodeSheep
 CodeSheep
发布于 07/12 05:51
字数 1908
阅读 1648
收藏 68
点赞 3
评论 4

Profile


概述

  • Dockerfile 是专门用来进行自动化构建镜像的编排文件(就像Jenkins 2.0时代的Jenkinsfile是对Jenkins的Job和Stage的编排一样),我们可以通过 docker build 命令来自动化地从 Dockerfile 所描述的步骤来构建自定义的 Docker镜像,这比我们去命令行一条条指令执行的方式构建高效得多。

  • 另一方面,由于 Dockerfile 提供了统一的配置语法,因此通过这样一份配置文件,我们可以在各种不同的平台上进行分发,需要时通过 Dockerfile 构建一下就能得到所需的镜像。

  • 最后一个必须提的优点便是:Dockerfile 通过与镜像配合使用,使得 Docker镜像构建之时可以充分利用 “镜像的缓存功能”,因此也提效不少!

然而写 Dockerfile 也像写代码一样,一份精心设计、Clean Code 的 Dockerfile 能在提高可读性的同时也大大提升Docker的使用效率

因此下面就结合实践来讲几条 Dockerfile 的实践心得!



基础镜像的选择有讲究

在我的文章 《利用K8S技术栈打造个人私有云(连载之:基础镜像制作与实验)》 中,我们是基于某个Linux基础镜像作为底包,然后打包进我需要的功能从而形成自己的镜像。

这里选择基础镜像时是有讲究的:

  • 一是 应当尽量选择官方镜像库里的基础镜像;
  • 二是 应当选择轻量级的镜像做底包

就典型的Linux基础镜像来说,大小关系如下:

Ubuntu > CentOS > Debian

因此相比 Ubuntu,其实更推荐使用最轻量级的 Debian镜像,而且它也是一个完整的Release版,可以放心使用



多使用标签Tag 有好处

  • 构建镜像时,给其打上一个易读的镜像标签有助于帮助了解镜像的功能,比如:
docker build -t=“centos:wordpress" .

例如上面的这个centos镜像是用来做wordpress用的,所以已经集成了wordpress功能,这一看就很清晰明了

  • 再者,我们也应该在 Dockerfile 的 FROM 指令中明确指明标签 Tag,不要再让 Docker daemon 去猜,如
FROM debian:codesheep


充分利用镜像缓存

什么是镜像缓存?

由 Dockerfile 最终构建出来的镜像是在基础镜像之上一层层叠加而得,因此在过程中会产生一个个新的 镜像层。Docker daemon 在构建镜像的过程中会缓存一系列中间镜像。

docker build镜像时,会顺序执行Dockerfile中的指令,并同时比较当前指令和其基础镜像的所有子镜像,若发现有一个子镜像也是由相同的指令生成,则 命中缓存,同时可以直接使用该子镜像而避免再去重新生成了。

为了有效地使用缓存,需要保证 Dockerfile 中指令的 连续一致,尽量将相同指令的部分放在前面,而将有差异性的指令放在后面

**举例:**假如我想用 Dockerfile方式 基于最基本的 CentOS 镜像来构建两个不同的镜像时,两个Dockerfile的开头可以相同:

FROM centos:latest

# 下面安装两个常用的工具
RUN yum install -y net-tools.x86_64

RUN yum install lrzsz

######## 上面为两个Dockerfile文件中相同的部分######

######## 下面为两个Dockerfile文件中不同的部分######

......



ADD 与 COPY 指令的正确使用

虽然两者都可以添加文件到镜像中,但在一般用法中,还是推荐以COPY指令为首选,原因在于ADD指令并没有COPY指令来的纯粹,ADD会添加一些额外功能,典型的如下 ADD 一个压缩包时,其不仅会复制,还会自动解压,而有时我们并不需要这种额外的功能。

ADD codesheep.tar.gz /path

除此之外,在需要添加多个文件到镜像中的时候,不要一次性集中添加,而是选择 按需 在必要时 逐个 添加即可,因为这样有利于利用镜像缓存



##尽量使用docker volume

虽然上面一条原则说推荐通过 COPY 命令来向镜像中添加多个文件,然而实际情况中,若文件 大而多 的时候还是应该优先用 docker -v 命令来挂载文件,而不是依赖于 ADD 或者 COPY



CMD 和 ENTRYPOINT指令 的正确理解使用

Dockerfile 制作镜像时,会组合 CMD 和 ENTRYPOINT 指令来作为容器运行时的默认命令:即 CMD + ENTRYPOINT。此时的默认命令组成中:

  • ENTRYPOINT 指令部分固定不变,容器运行时是无法修改的
  • 而 CMD 部分的指令也可以改变,表现在运行容器时,docker run 命令中提供的参数会覆盖CMD的指令内容。

举个例子:

FROM debian:latest

MAINTAINER codesheep@163.com

ENTRYPOINT [ "ls", "-l"]
CMD ["-a"]

若以默认命令运行容器,可以发现,执行的是 ls -a -l 命令:

ls -l -a

docker run 中增加参数 -t

docker run -it --rm --name test debian:codesheep -t

也可以发现执行的是 ls -l -t,即 Dockerfile 中的 CMD 原参数被覆盖了:

ls -l -t

因此推荐的使用方式是:

  • 使用exec格式的 ENTRYPOINT指令 设置固定的默认命令和参数

  • 使用 CMD指令 设置可变的参数



不推荐在 Dockerfile中 做端口映射

Dockerfile 可以通过 EXPOSE指令 将容器端口映射到主机端口上,但这样会导致镜像在一台主机上仅能启动一个容器!

所以应该在 docker run 命令中来用 -p 参数来指定端口映射,而不要将该工作置于 Dockerfile 之中:

#尽量避免这种方式
EXPOSE 8080:8899

#选择仅仅暴露端口即可,端口映射的任务交给 docker run 去做
EXPOSE 8080


使用 Dockerfile 来共享镜像

推荐通过共享 Dockerfile 的方式来共享镜像,优点多多:

  • 通过 Dockerfile 构建的镜像用户可以清楚地看到构建的过程

  • 就像 Jenkinsfile 可以加入版本控制从而追踪CI系统的变迁和步骤的回滚一样,Dockerfile 作为一个编排文件同样可以入库做版本控制,这样也可以回溯

  • 使用 Dockerfile 构建的镜像具有确定性,没有玄学的成分



后记

如果有兴趣,也可以抽点时间看看作者一些关于容器化、微服务化方面的文章:

作者相关的SpringBt实践文章在此:



© 著作权归作者所有

共有 人打赏支持
CodeSheep

CodeSheep

粉丝 124
博文 37
码字总数 50482
作品 0
南京
程序员
加载中

评论(4)

softxyz
softxyz
“Dockerfile 可以通过 EXPOSE指令 将容器端口映射到主机端口上,但这样会导致镜像在一台主机上仅能启动一个容器!”不太明白,感觉说的有问题,每个容器的ip都不一样,怎么会由于端口冲突导致容器冲突?
罗格林
罗格林
感谢分享! 一个小问题: Linux 镜像不是 Alpine 才是最小的吗 ?
Swire
Swire
ubuntu18.04的官方镜像相比于debian9和centos7,Ubuntu是最小的, 至于推荐debian,是因为官方推荐用debian而已。所以麻烦你搞清楚,写文章要负责点。
理工小强
理工小强
最好的办法不是手写 而是使用带有高亮提示的编辑器编写
Dockerfile 简版大全,附赠编写实例

Docker 逗你玩儿 - Git@OSC 联合灵雀云的 Docker 镜像征集活动,更有奖品赠送点击查看详情。 基础镜像可以用于创建Docker容器。镜像可以非常基础,仅仅包含操作系统;也可以非常丰富,包含灵...

oschina
2015/07/20
6.8K
11
快速构建docker镜像:maven插件

越来越多的项目开始了docker容器化部署的进化,在容器化之前我们部署一个项目,可能由源代码产出一个jar或者war即可直接发布了,启动之后是一个java进程;容器化之后,由源代码产出的是一个d...

rabbitGYK
04/15
0
0
Docker:使用多阶段构建镜像

多阶段构建是 Docker 17.05 及更高版本提供的新功能。这对致力于优化 Dockerfile 的人来说,使得 Dockerfile 易于阅读和维护。 致谢: 特别感谢 Alex Ellis 授权使用他的关于 Docker 多阶段构...

作者: Docker
2017/12/11
0
0
Dockerfile格式以及Dockerfile示例

笔记内容:Dockerfile格式以及Dockerfile示例 笔记日期:2018-02-07 25.13/25.14 Dockerfile创建镜像 –Dockerfile语法 25.15/25.16 Dockerfile创建镜像 –Dockerfile示例 Dockerfile创建镜像...

ZeroOne01
02/07
0
0
容器技术|Docker三剑客之Compose

本文已获得原作者霸都民工哥授权。 三剑客简介 docker-machine docker 技术是基于 Linux 内核的 cgroup 技术实现的,那么问题来了,在非 Linux 平台上是否就不能使用 docker 技术了呢?答案是...

掘金官方
07/06
0
0
九步构建自己的hello world Docker镜像

构建 Docker 镜像 Docker镜像构建是通过 Dockerfile来构建的,里面运行的程序是可以自定的,从编写程序到安装Docker镜像,可以一气呵成。接下来我们就通过九步实现一个自定义的镜像的制作、构...

上官瑾文
04/17
0
0
7 docker-使用dockerfile创建镜像

在前面的实验中我们多次用到的 Dockerfile,在本实验里我们将通过完成一个实例来学习Dockerfile的编写。 本节中,我们需要依次完成下面几项任务: Dockerfile 基本框架 Dockerfile 编写常用命...

DevOPS666
2017/08/22
0
0
利用Docker部署mongodb集群--分片与副本集

环境 Docker version 1.6.2 mongodb 3.0.4 第一步 编写Dockerfile并生成镜像 主意包含两个Dockerfile镜像,一个mongod的,一个mongos(在集群中负责路由) 编写Mongod的Dockerfile: FROM ub...

robin-yao
2015/06/22
0
7
DockerFile实战(二):DockerFile编写要求与基本风格

之前分享了一个Nginx的Dockerfile实战文章,但这是基于原有镜像的基础上去添加修改的,那么本文 来详细讲解一下,如何从ubuntu镜像生成一个Nginx镜像 Step1: #最开始,还是需要先搜索一个可...

Leon_zhang50773
2016/07/08
0
0
DOCKERFILE注意事项

准则 尽量将Dockerfile放在空目录中,如果目录中必须有其他文件,则使用.dockerignore文件。 避免安装不必须的包。 每个容器应该只关注一个功能点。 最小化镜像的层数。 多行参数时应该分类。...

Mr_sheng
2017/12/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

shell中的函数、shell中的数组、告警系统需求分析

shell中的函数 格式: 格式: function f_name() { command } 函数必须要放在最前面 示例1(用来打印参数) 示例2(用于定义加法) 示例3(用于显示IP) shell中的数组 shell中的数组1 定义数...

Zhouliang6
今天
2
0
用 Scikit-Learn 和 Pandas 学习线性回归

      对于想深入了解线性回归的童鞋,这里给出一个完整的例子,详细学完这个例子,对用scikit-learn来运行线性回归,评估模型不会有什么问题了。 1. 获取数据,定义问题     没有...

wangxuwei
今天
1
0
MAC安装MAVEN

一:下载maven压缩包(Zip或tar可选),解压压缩包 二:打开终端输入:vim ~/.bash_profile(如果找不到该文件新建一个:touch ./bash_profile) 三:输入i 四:输入maven环境变量配置 MAVEN_HO...

WALK_MAN
今天
0
0
33.iptables备份与恢复 firewalld的9个zone以及操作 service的操作

10.19 iptables规则备份和恢复 10.20 firewalld的9个zone 10.21 firewalld关于zone的操作 10.22 firewalld关于service的操作 10.19 iptables规则备份和恢复: ~1. 保存和备份iptables规则 ~2...

王鑫linux
今天
2
0
大数据教程(2.11):keeperalived+nginx高可用集群搭建教程

上一章节博主为大家介绍了目前大型互联网项目的系统架构体系,相信大家应该注意到其中很重要的一块知识nginx技术,在本节博主将为大家分享nginx的相关技术以及配置过程。 一、nginx相关概念 ...

em_aaron
今天
1
0
Apache Directory Studio连接Weblogic内置LDAP

OBIEE默认使用Weblogic内置LDAP管理用户及组。 要整理已存在的用户及组,此前办法是导出安全数据,文本编辑器打开认证文件,使用正则表达式获取用户及组的信息。 后来想到直接用Apache Dire...

wffger
今天
2
0
HFS

FS,它是一种上传文件的软件。 专为个人用户所设计的 HTTP 档案系统 - Http File Server,如果您觉得架设 FTP Server 太麻烦,那么这个软件可以提供您更方便的档案传输系统,下载后无须安装,...

garkey
今天
1
0
Java IO类库之BufferedInputStream

一、BufferedInputStream介绍 /** * A <code>BufferedInputStream</code> adds * functionality to another input stream-namely, * the ability to buffer the input and to * sup......

老韭菜
今天
0
0
STM 32 窗口看门狗

http://bbs.elecfans.com/jishu_805708_1_1.html https://blog.csdn.net/a1985831055/article/details/77404131...

whoisliang
昨天
1
0
Dubbo解析(六)-服务调用

当dubbo消费方和提供方都发布和引用完成后,第四步就是消费方调用提供方。 还是以dubbo的DemoService举例 -- 提供方<dubbo:application name="demo-provider"/><dubbo:registry address="z...

青离
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部