docker化一个前端工程流水线的总结

最近花了一段时间把主站的build pipeline docker化了,时间长到感觉自己的reputation都要被毁了。
在此总结下这个过程以及碰到的问题,希望对大家能有所帮助。

背景

这是一个纯前端的项目,两年前前后端分离的时候的项目,Grunt workflow,测试框架使用Karma,用Phantomjs1.8.2运行headless的测试,开发环境使用Chrome/Safari做功能性测试。开发环境基于node 0.12,一些基础设施的更新,部署的脚本,smoke test是基于Ruby的,版本为2.0

这个前端的工程部署在两个不同的AWS Region的S3上,互为fail over,最前面有Akamai为它们做负载均衡。

持续集成的工具使用Bamboo,部署在AWS上,所有的基础设施都由cloudformation来管理,其agent需要有ruby 2.0node 0.12Phantomjs 1.8.2的环境才可以运行具体的任务。整个过程已经做到了持续部署,一个完整的build过程如下:

  1. 提交代码
  2. trigger build,执行单元测试和集成测试
  3. 自动部署staging 环境
  4. 自动部署production 环境
  5. 对部署后的产品做性能测试
  6. 上传工程中依赖的第三方类库信息到S3 bucket(出于安全的考虑)

存在的问题

太长时间没有人做技术上的升级,导致下面的一些隐患和问题:

  1. 开发的工具版本落后,node当前版本已经是6.3了,ruby 2.0的版本应该已经不维护了,同样,对应的Karma,Phantomjs都以及更新了很多
  2. 运行build依赖的agent是共用的,如果有人对agent的环境进行修改,会影响该项目的持续集成
  3. 未来需要将CI工具从Bamboo迁移到Buildkite,用pipeline as code的方式去构建,每个组自己去管理build agent,使用Docker会更加方便迁移

过程以及遇到的一些难点

测试部分通过的过程及问题

  1. 首先做的事情是构建一个基础的docker 镜像,包含最新的node 6.3.1,phantomjs 2.1.1,后来发现其实不用Phantomjs,这个有点多余了。 成果在这里: https://github.com/iambowen/node_on_docker,因为这样的环境更加通用些,所以才publish到官方的docker repository里面。
  2. 在这个镜像的基础上,构建一个我们工程依赖环境的基础镜像,额外安装了Ruby 2.3,最新的Chrome,git以及一些git的配置,因为需要从企业版github上pull代码。
  3. 本地升级node版本,以及相关的grunt,karma,Phantomjs的版本,运行测试通过。
  4. 将工程mount容器中,然后运行测试,npm install失败,原因是安装fsevent出错。查看了下这个包,原来只是给OSX下使用的。删除npm-shrinkwrap.json后重新运行可以通过。原因是有人在OSX下运行了npm shrinkwrap去生成的这个锁定版本的文件,真是烦人。于是反其道行之在容器里面生成npm-shrinkwrap.json,在host上运行测试一切完好,就这样解决了这个问题。
  5. 在Bamboo创建一个branch,然后针对我的分支代码运行测试
  6. 测试里面的一个步骤是做bower install安装第三方js类库,但是比较恶心的是,有些第三方类库是以git的协议去下载,而不是https。本地运行一切都好,但是在Bamboo Agent上运行的时候却出现了连接超时的问题,很有可能是Bamboo所在AWS的network ACL或者是security group没有允许9418端口的TCP访问。不过最后解决的方式并不是修改防火墙或者将协议改为https,而是直接把类库checking到git中,这样对应的修改Gruntfile,不用再运行bower install。check in之后在Bamboo上运行还是失败,本地却可以通过,仔细检查,原来是一部分bower module目录名为dist被git ignore掉了。

通过测试后,接下来就是部署了。部署要解决的问题是,如何让容器拿到AWS role的动态权限去做文件的上传更新操作。ECS好像是支持容器去assume role的操作,但是我们没有用ECS,所以只能考虑其它方式。

我想到的方式在bamboo 的 docker agent上 assume role,拿到对应的credential后,将其作为环境变量传入到容器中。实验证明这样的方式是可行的,万幸bamboo的docker agent支持aws cli命令,不过没有jq稍微增大了点提取credential的难度,脚本如下:

if [ "$DEPLOY_ENV" = "staging" ]; then
  AWS_ACCOUNT_ID='1111111111'
elif [ "$DEPLOY_ENV" == "production" ]; then
  AWS_ACCOUNT_ID='2222222222'
fi

credentials=$(aws sts assume-role  --role-arn    arn:aws:iam::"$AWS_ACCOUNT_ID":role/roleName \
          --role-session-name roleSessionName \
            --query 'Credentials.[SecretAccessKey, SessionToken, AccessKeyId]'  \
            --output text)

SecretAccessKey=$(echo $credentials | cut -d' ' -f1)
SessionToken=$(echo $credentials | cut -d' ' -f2)
AccessKeyId=$(echo $credentials | cut -d' ' -f3)

docker run  -e BUILD_VERSION="$BUILD_VERSION" \
    -e DEPLOY_ENV="$DEPLOY_ENV" -e AWS_SECRET_ACCESS_KEY="$SecretAccessKey" \
    -e AWS_SESSION_TOKEN="$SessionToken" -e AWS_ACCESS_KEY_ID="$AccessKeyId" --rm docker_image bash -c 'grunt deploy'

因为部署是用aws node 的sdk,所以读取的环境变量名字不太一样,要稍微注意下。

在CI上运行后,staging部署通过,手动在bamboo的docker agent上测试下是否能assume产品环境的部署的role,结果可以,那就是说产品环境的部署应该也可以通过了。

总结

  1. npm sucks,更糟糕的是程序员在引入依赖的时候缺乏考虑,我在package.json里面见到了不少无人维护的component,后续的升级维护是一个问题,联想以前的ruby项目也是一样。一旦有版本升级,碰到无人维护的gem时会非常痛苦。
  2. 一个工程里面用了太多的语言,也是一件很糟糕的事情,明明可以用node的aws sdk来做到所有的部署,不知道为何用ruby去实现,无形中增大了维护的成本。
  3. 一般来说,我们认为docker可以保证不同环境的一致性,但是由于一些特殊原因,如我上面提到的防火墙问题,bower module被git ignore掉的问题,在CI环境下才能暴露出来。所以在PR被merge到master之前,一定要保证修改在CI上也运行通过。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • Docker — 云时代的程序分发方式 要说最近一年云计算业界有什么大事件?Google Compute Engi...
    ahohoho阅读 15,505评论 15 147
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,579评论 18 139
  • 什么是基础设施 在IT领域,当我们谈论基础设施时,我们都在谈论什么呢?一般来讲,我们会直觉的认为服务器就是基础设施...
    iambowen阅读 11,331评论 2 38
  • Docker工具分类列表 编排和调度 持续集成/持续部署(CI / CD) 监控 记录 安全 存储/卷管理 联网 ...
    Anoyi阅读 3,719评论 1 44
  • 夏是狂热的, 家是遥远的, 若有人问我生活如何, 我是说不出的。 我说不出我的生活, 若有人问我生活如何, 夏是狂...
    枞阳徐少阅读 180评论 0 0