高效编写Dockerfile的几条准则
概述
- 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
命令:
若 docker run
中增加参数 -t
docker run -it --rm --name test debian:codesheep -t
也可以发现执行的是 ls -l -t
,即 Dockerfile 中的 CMD 原参数被覆盖了:
因此推荐的使用方式是:
- 使用exec格式的 ENTRYPOINT指令 设置固定的默认命令和参数
- 使用 CMD指令 设置可变的参数
不推荐在 Dockerfile中 做端口映射
Dockerfile 可以通过 EXPOSE指令 将容器端口映射到主机端口上,但这样会导致镜像在一台主机上仅能启动一个容器!
所以应该在 docker run
命令中来用 -p
参数来指定端口映射,而不要将该工作置于 Dockerfile 之中:
#尽量避免这种方式 EXPOSE 8080:8899 #选择仅仅暴露端口即可,端口映射的任务交给 docker run 去做 EXPOSE 8080
使用 Dockerfile 来共享镜像
推荐通过共享 Dockerfile 的方式来共享镜像,优点多多:
- 通过 Dockerfile 构建的镜像用户可以清楚地看到构建的过程
- 就像 Jenkinsfile 可以加入版本控制从而追踪CI系统的变迁和步骤的回滚一样,Dockerfile 作为一个编排文件同样可以入库做版本控制,这样也可以回溯
- 使用 Dockerfile 构建的镜像具有确定性,没有玄学的成分
后记
如果有兴趣,也可以抽点时间看看作者一些关于容器化、微服务化方面的文章:
- 从一份配置清单详解Nginx服务器配置
- 利用K8S技术栈打造个人私有云 连载文章
- Docker容器可视化监控中心搭建
- 利用ELK搭建Docker容器化应用日志中心
- 利用TICK搭建Docker容器可视化监控中心
- RPC框架实践之:Apache Thrift
- RPC框架实践之:Google gRPC
- 微服务调用链追踪中心搭建
- Docker容器跨主机通信
- Docker Swarm集群初探
作者相关的SpringBt实践文章在此:
- SpringBoot应用部署于外置Tomcat容器
- ElasticSearch搜索引擎在SpringBt中的实践
- 初探Kotlin+SpringBoot联合编程
- Spring Boot日志框架实践
- SpringBoot优雅编码之:Lombok加持
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Auto Scaling 伸缩配置支持镜像预设密码
功能说明 什么是镜像预设密码 如果您的一个 ECS 实例设置了密码(用于远程登录 ECS),则通过该实例制作的快照进而通过该快照创建出来了一个自定义镜像,该镜像即被认为 镜像中预设了密码。若您使用该自定义镜像来创建新的伸缩配置,然后通过该配置弹出来的ECS的密码值就会是镜像中预设的密码。 前置条件 创建伸缩配置时选镜像为 自定义镜像/共享镜像,且所选镜像已经预设了密码。 通过该伸缩配置弹机器 操作步骤 制作带密码的自定义镜像 对带有密码的实例的系统盘【创建快照】 通过快照【创建自定义镜像】 前往 Auto Scaling 控制台 选择某个伸缩组后,创建伸缩配置 2.1 选择【自定义镜像】 ![image](https://yqfile.alicdn.com/4e71b6c43551ab4a2bc4c9dd97587313a0378dbb.png) &l
- 下一篇
Freebsd for ECS 系统盘扩容示例
背景: 由于历史遗留问题,Freebsd 系统盘出厂大小是 20G,即使购买的系统盘大小大于 20G,系统内分配的也是 20G 大小,那么云上的 Freebsd 如何扩容系统盘呢? 怂一下先: 请对生产环境,保持敬畏之心,务必做好快照备份! 请对生产环境,保持敬畏之心,务必做好快照备份! 请对生产环境,保持敬畏之心,务必做好快照备份! 1,查看磁盘信息,不同于 CentOS/Ubuntu系统使用fdisk,Freebsd 使用gpart 查看磁盘分区信息 # gpart show => 63 83886017 vtbd0 MBR (40G) 63 1 - free - (512B) 64 41942975 1 fr
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS关闭SELinux安全模块
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7设置SWAP分区,小内存服务器的救世主