- 最小化处理变更文件,仅变更下一步所需的文件,以尽可能减少构建过程中的缓存失效 。
- 对于处理文件变更的 ADD 命令、COPY 命令,尽量延迟执行 。
- Docker 是以层为单位上传镜像仓库的,这样也能最大化的利用缓存的能力 。因此,执行结果很少变化的命令需要抽出来单独成层,如上面提到的
npm install
的例子里,也用到了这方面的思想 。
- 如果镜像层数越少,总上传体积就越小 。因此,在命令处于执行链尾部,即不会对其他层缓存产生影响的情况下,尽量合并命令,从而减少缓存体积 。例如,设置环境变量和清理无用文件的指令,它们的输出都是不会被使用的,因此可以将这些命令合并为一行 RUN 命令 。
RUN set ENV=prod && rm -rf ./trash
- Docker cache 的下载也是通过层缓存的方式,因此为了减少镜像的传输下载时间,我们最好使用固定的物理机器来进行构建 。例如在流水线中指定专用宿主机,能是的镜像的准备时间大大减少 。
这里我的建议是,优先保证构建时间,其次在不影响时间的情况下,尽可能的缩小构建缓存体积 。
以 Docker 的思维管理服务避免使用进程守护我们编写传统的后台服务时,总是会使用例如 pm2、forever 等等进程守护程序,以保证服务在意外崩溃时能被监测到并自动重启 。但这一点在 Docker 下非但没有益处,还带来了额外的不稳定因素 。
首先,Docker 本身就是一个流程管理器,因此,进程守护程序提供的崩溃重启,日志记录等等工作 Docker 本身或是基于 Docker 的编排程序(如 kubernetes)就能提供了,无需使用额外应用实现 。除此之外,由于守护进程的特性,将不可避免的对于以下的情况产生影响:
- 增加进程守护程序会使得占用的内存增多,镜像体积也会相应增大 。
- 由于守护进程一直能正常运行,服务发生故障时,Docker 自身的重启策略将不会生效,Docker 日志里将不会记录崩溃信息,排障溯源困难 。
- 由于多了个进程的加入,Docker 提供的 CPU、内存等监控指标将变得不准确 。
pm2-runtime
,但我仍然不推荐大家使用进程守护程序 。其实这一点其实是源自于我们的固有思想而犯下的错误 。在服务上云的过程中,难点其实不仅仅在于写法与架构上的调整,开发思路的转变才是最重要的,我们会在上云的过程中更加深刻体会到这一点 。
日志的持久化存储无论是为了排障还是审计的需要,后台服务总是需要日志能力 。按照以往的思路,我们将日志分好类后,统一写入某个目录下的日志文件即可 。但是在 Docker 中,任何本地文件都不是持久化的,会随着容器的生命周期结束而销毁 。因此,我们需要将日志的存储跳出容器之外 。
最简单的做法是利用
Docker Manager Volume
,这个特性能绕过容器自身的文件系统,直接将数据写到宿主物理机器上 。具体用法如下:docker run -d -it --name=app -v /app/log:/usr/share/log app
运行 docker 时,通过-v 参数为容器绑定 volumes,将宿主机上的
经验总结扩展阅读
- 记一次 .NET 某企业OA后端服务 卡死分析
- Docker | 使用dockerfile生成镜像,清理docker空间
- 配置DNS域名解析服务
- CRESDA 陆地观测卫星数据服务订单ftp地址错误—已解决不能下载问题
- 服务员上鱼的正确方法
- Docker | 数据持久化与数据共享
- 泰到位服务3个小时干什么了
- Docker | Compose创建mysql容器
- 糟了,线上服务出现OOM了
- 物业服务不到位物业费可以不交吗