docker-compose下载慢_编写Docker Compose时要注意的五大常见错误

859e365e5c9df5cdef51c4777e581699.gif

508b88313d753a19b5431bc87c5f5ae2.png

在构建容器化的应用时,开发人员往往需要某种方法来引导启动目标容器,以对其进行代码级别的测试。尽管业界有许多方法可以实现该目的,但Docker Compose是目前最受欢迎的一种方法。它能够让如下两个方面变得容易实现:
  • 指定在开发过程中需要启动的容器。
  • 设置一套快速的代码测试调试(code-test-debug),以方便开发循环。
通常情况下,团队事先编写一个docker-compose.yml文件,指定开发所需的所有内容,并将其提交给存储库。然后,每个开发人员只需运行docker-compose up,即可启动测试其代码所需的所有容器。不过,要让docker-compose的设置能够达到最佳性能状态,例如:在不到一分钟之内启动开发环境,并且在几秒钟内完成对每个更改的测试,这些都需要团队花费大量的工作。在这些准备过程中,由于各个开发人员每天花费在测试其代码上的时间各不相同,而且任何细微的改动,都可能会对整个开发团队的生产力产生巨大的影响。因此,我们有必要在此讨论他们在编写Docker Compose时常见的五大错误,及其对应的解决方法。

错误1:频繁地进行容器重建

Docker的构建往往比较耗时,特别是每次针对代码的变更开展测试的时候。如果能够节省此方面的时间,那么对于加快开发周期来说是十分有益的。过去,对于非容器化的应用,我们通常会采取如下传统的工作流程:
  • 编写代码
  • 构建
  • 运行
多年来,业界持续优化该流程,并提出了诸如:针对编译语言的增量构建和热重载(hot reloading)等实用技巧。随着容器技术的出现,我们在现有的工作流程中增加了docker构建的步骤,如下图所示。
  • 编写代码
  • 构建
  • Docker构建
  • 运行
当然,如果构建得不好,那么docker构建步骤也可能会带来额外的时间开销。例如:使用apt-get进行依赖项的重载步骤。有时候,这些步骤可能会让整个测试过程比添加Docker之前还要慢。解决方案:在Docker外部运行代码第一种解决方法是在Docker Compose中启动所有的依赖项,然后在本地运行测试代码。此举模仿了非容器化应用开发的工作流程。您只需向localhost公布依赖关系,然后将正在使用的服务指向所有的localhost:地址即可。但是,该方法并非永远可行,如果您正在使用的是代码依赖容器镜像中的内置元素时,那么用户电脑就不一定能够访问到具体内容。解决方案:最大化缓存,以优化Dockerfile如果必须构建Docker镜像,那么我们可以编写Dockerfile,通过最大化缓存,将Docker的构建时间从原来的10分钟压缩至1分钟。在生产环境中,Dockerfile的典型模式是通过将单个命令链接到一条RUN语句中,来减少层级的数量。毕竟,在开发过程中镜像的大小并不重要,重要的是层级的数量。下面展示的是在生产环境中的一个Dockerfile文件:
RUN \ 
go get -d -v \
&& go install -v \
&& go build
不过,该命令在每次被重新运行时,Docker都会重新下载所有的依赖项,并重新安装它们。我们可以通过增量构建(incremental build)来提供效率。同时,您可以将开发专用的Dockerfile其分成几个短小的步骤,从而使得那些经常更改的代码步骤被排到最后,而将鲜少更改的步骤(例如拉式依赖关系)被放在首位。因此,在重建Dockerfile时,您不必构建整个项目,而只需构建那些被已更改的少量末尾块即可。有关此方面的案例,您可以参阅以下用于Blimp(请参见--https://kelda.io/blimp)开发的Dockerfile。通过遵循上述方法,您可以将繁琐的构建过程缩减到了几秒钟之内完成。
FROM golang:1.13-alpine as builder 
RUN apk add busybox-static
WORKDIR /go/src/github.com/kelda-inc/blimp
ADD ./go.mod ./go.mod
ADD ./go.sum ./go.sum
ADD ./pkg ./pkg
ARG COMPILE_FLAGS
RUN CGO_ENABLED=0 go install -i -ldflags "${COMPILE_FLAGS}" ./pkg/...
ADD ./login-proxy ./login-proxy
RUN CGO_ENABLED=0 go install -i -ldflags "${COMPILE_FLAGS}" ./login-proxy/...
ADD ./registry ./registry
RUN CGO_ENABLED=0 go install -i -ldflags "${COMPILE_FLAGS}" ./registry/...
ADD ./sandbox ./sandbox
RUN CGO_ENABLED=0 go install -i -ldflags "${COMPILE_FLAGS}" ./sandbox/...
ADD ./cluster-controller ./cluster-controller
RUN CGO_ENABLED=0 go install -i -ldflags "${COMPILE_FLAGS}" ./cluster-controller/...
RUN mkdir /gobin
RUN cp /go/bin/cluster-controller /gobin/blimp-cluster-controller
RUN cp /go/bin/syncthing /gobin/blimp-syncthing
RUN cp /go/bin/init /gobin/blimp-init
RUN cp /go/bin/sbctl /gobin/blimp-sbctl
RUN cp /go/bin/registry /gobin/blimp-auth
RUN cp /go/bin/vcp /gobin/blimp-vcp
RUN cp /go/bin/login-proxy /gobin/login-proxy
FROM alpine
COPY --from=builder /bin/busybox.static /bin/busybox.static
COPY --from=builder /gobin/* /bin/
最后值得一提的是:随着多阶段构建(multi-stage builds,请参见--https://docs.docker.com/develop/develop-images/multistmuage-build/)的引入,我们如今可以创建各种具有良好分层和较小镜像的Dockerfile。不过,我们在此并不会展开详细的讨论。解决方案:使用主机卷(host volumes)大多数语言都会提供一种方法来监视程序代码,并在代码发生更改时自动重新运行。例如,nodemon就是JavaScript语言的一种Node自动重启工具(请参见--https://www.npmjs.com/package/nodemon)。由于主机卷可以将您电脑上的目录,镜像到正在运行的容器之中,因此您在使用文本编辑器来编辑文件时,各种更改将会被自动同步到容器中,并在容器内被立即执行。最初,您可能需要花点时间进行前期准备,之后在Docker中,您可以在1-2秒内马上看到代码的更改结果。因此,我们会选择使用主机卷将代码直接挂载到容器中,以便以原生的方式,在包含其了运行时依赖项的Docker容器中运行自己的代码。

错误2:缓慢的主机卷

如果您使用过主机卷,那么是否已经注意到:在Windows和Mac上读写文件的速度可能会非常缓慢?其实,对于诸如Node.js和具有复杂依赖性的PHP应用程序之类,需要读写大量文件的命令而言,这是一个已知的问题。其背后的原因是:Docker主要运行在Windows和Mac上的VM中。而我们在进行主机卷的挂载时,它必须经过大量的转换,才能使文件夹进入容器,这有点类似于网络文件系统。而此类额外的开销,在Linux本地运行Docker时,则不会出现。解决方案:放宽强一致性该问题的一个关键原因是:文件系统在默认挂载时,需要保持强一致性。也就是说:所有特定文件的读写进程都必须统一对于文件修改的顺序,以便让文件的内容达成最终的一致。可是,强一致性的代价非常昂贵,它需要所有文件的写入进程之间持续保持协调,以确保它们不会干扰或破坏彼此的更改。虽然在生产环境中的数据库需要保持强一致性。但是在开发过程中,由于写入进程就是代码文件本身,目标就是我们的存储库,因此强一致性就不那么必需了。那么,我们就可以考虑Docker在挂载卷时,放宽强一致性。例如:在Docker Compose中,我们可以简单地将此cached关键字添加到卷挂载中,以获得显著的性能保证。对应的代码如下:
volumes: 
- "./app:/usr/src/app/app:cached"
注意:此举仅适合开发环境,不适合生产环境。解决方案:代码同步另一种处置方法是设置代码的同步。您可以使用工具侦测主机和容器之间的变化,通过复制文件来解决差异(类似于rsync),而不是挂载卷。Docker在最新的版本中内置了用来替代卷的缓存模式--Mutagen(请参见--https://mutagen.io/)。此外,上文提到的Blimp则使用Syncthing(请参见--https://http//syncthing.net/)实现了类似的功能。解决方案:不要挂载软件包Node之类的语言通常会把大部分文件操作放在packages目录中(如node_modules)。那么,我们可以试着从卷中去除此类目录,以显著提高性能。下列示例是一个将代码挂载到容器中的专属卷,它覆盖了node_modules目录。
volumes:  
- ".:/usr/src/app"
- "/usr/src/app/node_modules"
该挂载操作会告诉Docker去使用node_modules目录下的标准卷,以使得在npm install运行时,不再使用慢速的主机挂载方式。为了使该工作能够正常进行,我们应该在容器首次启动时,在entrypoint中执行npm install,以安装依赖项,并更新node_modules目录。具体代码如下:
entrypoint: 
- "sh"
- "-c"
- "npm install && ./node_modules/.bin/nodemon server.js"
如果您想查看并运行上述完整的示例,请参考--https://kelda.io/blimp/docs/examples/#nodejs。

错误3:脆弱的配置

如果您曾深入研究过代码,您可能会发现Docker Compose中也充斥着各种大量复制和粘贴而来的代码。显然,我们需要干净整洁的Docker Compose文件,以方便轻松地按需做出修改。解决方案:使用各种env文件Env文件能够将环境变量与Docker Compose主配置分开,以实现:
  • 避免将代码泄露到git的历史记录中。
  • 开发人员都能按需自定义设置。例如,每个开发人员都可以持有一个唯一的访问密钥。他们通过将配置保存在.env文件中,以实现不必修改已提交的docker-compose.yml文件,也不必在文件更新时处理各种冲突问题。
如果您想使用环境文件,只需添加一个.env文件,或设置带有env_file字段的显式路径即可(请参见--https://docs.docker.com/compose/environment-variables/#the-env_file-configuration-option)。

解决方案:使用替代文件

替换文件(请参见--https://docs.docker.com/compose/extends/)可以方便您在具有基本配置的基础上,在其他文件中指定各项修改。该功能非常适合Docker Swarm及其YAML文件。您可以将生产环境的配置存储在docker-compose.yml中,然后在替代文件中,指定开发所需的任何修改(例如:使用主机卷)。解决方案:使用extends如果您使用的是Docker Compose v2,那么就可以使用extends关键字,在多个位置导入YAML片段。例如,您可能会定义:公司里所有的服务都需要在开发的Docker Compose文件中带有某五个特定的配置。然后您可以使用extends关键字将其放置到任何需要的地方,以实现模块化。当然,如果仅在YAML中执行此项操作可能比较繁琐,我们完全可以通过编程来实现。虽然Compose v3删除了对于extends关键字的支持。但是,您仍然可以使用YAML anchors(请参见--https://support.atlassian.com/bitbucket-cloud/docs/yaml-anchors/)来实现类似的结果。

错误4:乱序启动(Flaky Boots)

如果docker-compose出现了崩溃,我们能够仅使用docker-compose restart来重启服务吗?其实此类问题主要与服务错误的启动顺序有关。例如,您的Web应用可能依赖于数据库,那么在Web应用启动时,如果数据库尚未准备就绪,就会出现崩溃。解决方案:使用depends_ondepends_on使您可以控制启动的顺序。默认情况下,depends_on仅判断依赖项是否已经创建,而不会判断依赖项是否“健康”。虽然Docker Compose v2能够支持将depends_on与运行状况的检查相结合。不过,该功能也在Docker Compose v3中被去除了。当然,您可以使用诸如wait-for-it.sh之类的脚本,来手动实现类似的功能。和上面提到的放宽强一致性相同,虽然Docker文档不建议在生产环境中使用depends_on和wait-for-it.sh,来为容器指定特定的启动顺序。但是对于开发而言,我们完全可以用到depends_on。

错误5:资源管理不善

如果您碰到开发流程受阻,Docker无法全速运行,或是无法平稳地获取运行所需的资源,那么您可以考虑以下几个方面:解决方案:更改Docker Desktop的分配Docker Desktop需要大量的RAM和CPU,尤其是在Mac和Windows的VM上。Docker Desktop的默认配置往往不会分配足够的RAM和CPU,因此我们通常需要调整相关的设置。在开发时,我经验是:为Docker分配大约8GB的RAM和4个CPU,并且在不使用Docker Desktop时,及时关闭之。解决方案:删除未使用的资源人们在使用Docker时经常会出现数百个卷与旧的容器镜像。这在无形中浪费了各种资源。为了释放这些资源,我们建议通过间或运行docker system prune的方式,以删除当前未使用到的所有卷、容器和网络。

总结

总的说来,为了改善开发人员在使用Docker Compose时的体验,我建议您做到如下五点:
  • 最小化容器的重建。
  • 使用主机卷。
  • 像对待代码那样,认真配置文件,以便于维护。
  • 让启动更加可靠。
  • 认真分配管理资源。
此外,您还可以通过链接--https://kelda.io/blog/docker-volumes-for-development/,以获悉如何设置主机卷,并加快Docker开发。

Java帮帮

非盈利学习社区

官网:www.javahelp.com.cn

27387fe793450b273dd087b5a3c57137.png

职涯宝

帮助职业者成功

分享优质内容

官网:zhiya360.com

0d9e8da5d2eeb33afe0f2674f4dafd3d.png

九点编程

深夜学习,未来可期

c952be1c148f7e588fe4ba93ea89d87f.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457804.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

frame越过另一个frame_拥抱swoole(三)之用php实现一个混合服务器

混合服务器,就是可以同时支持http,websocket,tcp等的服务器,用swoole就是这么简单,分分钟,就可以愉快地搞物联网开发了,啥都支持,我采用官方的例子,创建一个混合服务器&a…

Hibernate学习系列————注解一对多单向实例

2019独角兽企业重金招聘Python工程师标准>>> 开发环境:MysqlEclipse 一对多单向的列子原理:一个班级,多个学生,学生端为多的一端,他们拥有一个外键指向相同的班级。 项目结构 需要的jar包 hibernate.cfg.xm…

sudo apt-get nmap 报错锁占用

在Ubuntu中用apt-get命令安装软件是出现如下错误: 网上搜了一下原因,说是有另外一个程序在运行,导致锁不可用,原因可能是赏析运行更新或安装没有正常完成。这是因为上次更新或者安装没有正常完成。 网上的两种解决方法&#xff1…

python逐行读取txt写入excel_用python从符合一定格式的txt文档中逐行读取数据并按一定规则写入excel(openpyxl支持Excel 2007 .xlsx格式)...

前几天接到一个任务,从gerrit上通过ssh命令获取一些commit相关的数据到文本文档中,随后将这些数据存入Excel中。数据格式如下图所示观察上图可知,存在文本文档中的数据符合一定的格式,通过python读取、正则表达式处理并写入Excel文…

Extjs 之 initComponent 和 constructor的区别(转)

在创建自定义类时,先构造(constructor)后初始化(initComponent)。如:(在旧的Extjs 版本中使用 Ext.extend 实现扩展) Ext.define(Btn,{ extend:Ext.button.Button, init…

hive遍历_从Hive中的stored as file_foramt看hive调优

一、行式数据库和列式数据库的对比1、存储比较行式数据库存储在hdfs上式按行进行存储的,一个block存储一或多行数据。而列式数据库在hdfs上则是按照列进行存储,一个block可能有一列或多列数据。2、压缩比较对于行式数据库,必然按行压缩&#…

帮助孩子学会感恩_页数204_出版日期2015.03_完整版PDF电子书下载

帮助孩子学会感恩_页数204_出版日期2015.03_完整版PDF电子书下载 带索引书签目录高清版_13813212 下载链接http://pan.baidu.com/s/1geEmUeZ 【作 者】(英)蒂姆惠特尼(TimWhitney)著【丛书名】陪孩子成长系列丛书【形态项】 204 …

xwpftablecell设置字体样式_HTML的文字样式

font 属性可以用来作为 font-style, font-variant, font-weight, font-size, line-height 和 font-family 属性的简写,或将元素的字体设置为系统字体。字体修改font-family 属性:设置HTML页面中的字体font-size 属性:设置字体大小font-weight…

15-CSS基础-浮动流

浮动 网页的布局方式 什么是网页的布局方式? 网页的布局方式其实就是指浏览器是如何对网页中的元素进行排版的 标准流(文档流/普通流)排版方式 其实浏览器默认的排版方式就是标准流的排版方式在CSS中将元素分为三类, 分别是块级元素/行内元素/行内块级元素在标准流中有两种排版…

git-- 使用

git 使用时两个人冲突: Resolve conflicts

高内聚低耦合通俗理解_抱歉,请不要把“业务逻辑层”理解为“业务中台”

在IAS2019中台架构峰会上,我曾与一位年轻帅气的技术小伙来了一番有趣的对话。因为和朋友有约,所以我在现场互动结束之后,就急匆匆地跟其他嘉宾打了声招呼,抱着笔记本冲出了会场。但没想到刚到电梯口,却被一位帅小伙迎面…

org-mode入门教程

org-mode 入门教程By Z.H. Fu切问录 www.fuzihao.orgorg-mode 入门教程 org-mode是Emacs提供的一个强大的编辑模式,可以用于做会议笔记以及制作各种待办事项(GDT)。其语法类似于Markdown但是提供了比Markdown更多的操作,再加上Ema…

如何对web.config进行加密和解密

http://blog.csdn.net/jf_jifei/article/details/6527390 在WEB网站开发过程中,如果我们将数据库连接字符串封装到.DLL文件中,将会给数据库和程序的迁移带来麻烦,因为万一服务器地址或者数据库发生变更,那么我们就不得不修改源程序…

java 爬虫_Java原生代码实现爬虫(爬取小说)

Java也能做爬虫。现在提到爬虫人第一个想到的就是python,其实使用Java编写爬虫也是很好的选择,Java成熟的爬虫框架很多,下面给大家展示一个使用Java基础语言编写的爬取小说的案例:实现功能:爬取目标网站全本小说代码编…

JS window对象 Location对象 location用于获取或设置窗体的URL,并且可以用于解析URL。 语法: location.[属性|方法]...

Location对象 location用于获取或设置窗体的URL&#xff0c;并且可以用于解析URL。 语法: location.[属性|方法] location对象属性图示: location 对象属性&#xff1a; location 对象方法: 任务 在右边编辑器script标签内&#xff0c;获取当前显示文档的URL,并输出。 <!DOC…

java 数据结构_Java版-数据结构-队列(数组队列)

前言看过笔者前两篇介绍的 Java版数据结构 数组和 栈的盆友&#xff0c;都给予了笔者一致的好评&#xff0c;在这里笔者感谢大家的认可&#xff01;&#xff01;&#xff01;由于本章介绍的数据结构是 队列&#xff0c;在队列的实现上会基于前面写的 动态数组来实现&#xff0c…

ssh 介绍 和使用 程序不挂起

目录 SSH的安全机制 SSH的安装 启动服务器的SSH服务 SSH两种级别的远程登录 SSH的高级应用 Secure Shell(SSH) 是由 IETF(The Internet Engineering Task Force) 制定的建立在应用层基础上的安全网络协议。它是专为远程登录会话(甚至可以用Windows远程登录Linux服务器进行…

java 四舍五入_Java常用类

每个人的心里&#xff0c;都藏着一个了不起的自己&#xff0c;只要你不颓废&#xff0c;不消极&#xff0c;一直悄悄酝酿着乐观&#xff0c;培养着豁达&#xff0c;坚持着善良&#xff0c;只要在路上&#xff0c;就没有到达不了的远方&#xff01;BigInteger在Java中&#xff0…

Sublime 插件- px 转rem

一个CSS的px值转rem值的Sublime Text 3自动完成插件。 插件效果如下&#xff1a; 安装 克隆项目 https://github.com/hyb628/cssrem.git进入packages目录&#xff1a;Sublime Text -> Preferences -> Browse Packages...复制下载的cssrem目录到刚才的packges目录里。重…

window8下安装RabbitMQ

2019独角兽企业重金招聘Python工程师标准>>> 1.下载并安装erlang&#xff0c;http://www.erlang.org/download.html。64位的下载的是otp_win64_19.1.exe 查看是否安装成功&#xff1a; 2.下载RabbitMQ,最新版是2.8.1&#xff0c;http://www.rabbitmq.com/releases/r…