使用travis-ci如何持续部署node.js应用详解


Posted in Javascript onJuly 30, 2017

前言

在开始之前,我们先来简单介绍下Travis-ci,Travis-ci是一款持续集成(Continuous Integration)服务,它能够很好地与Github结合,每当代码更新时自动地触发集成过程。

Travis-ci配置简单,很多nodejs项目都用它做自动测试。然而,对于持续集成,仅做到自动测试是不够的,还要有后续的自动部署,才能完成“提交代码 => 自动测试 => 自动部署”的集成链条。

本文以nodejs应用为例,来谈谈如何利用travis-ci完成自动部署。话不多说,来一起看看详细的介绍:

基本原理

从自动测试到自动部署的核心问题是测试机与生产服务器的信任问题,即如何安全地把程序包传输到生产服务器。市面上的部署工具如scp、ansible、chef,都绕不开这个核心问题。

以scp为例,测试机登录生产服务器的方式有两种:密码和秘钥。密码登录方式需要交互式地输入密码,总不能每次测试的时候,人为地输入密码吧,所以密码方式行不通。

秘钥的方式可以实现自动登录,但首次将测试机的公钥传输给生产服务器仍然需要密码。似乎走入了死胡同,但办法总是有的。我们知道开发机是可以登录到生产服务器的,那么我们就可以将开发机的公钥复制到生产服务器,将开发机的私钥复制到测试机,测试机通过私钥来伪装成开发机,自动地登录到生产服务器。

解决了自动登录的问题,另一个问题是怎么将开发机的私钥复制到测试机上。由于测试机每次都是新开的一个虚拟机,这个新开的虚拟机IP不固定,所以没办法直接登录上去。解决办法是将私钥文件作为代码库的一部分提交,这样测试机每次从代码库上拉取代码的同时也获取到了秘钥文件,通过这种方式就实现了私钥从开发机复制到测试机。

将私钥文件提交到代码库有一个很严重的安全性问题,即任何人只要得到了这个私钥文件,他就可以随心所欲的操纵生产服务器。幸好,travis-ci提供了加密方案,它能够将私钥文件加密,加密后的文件只在当前代码库有效。

总的来说,通过复制私钥完成自动登录以及对私钥加密来保障安全性,我们就可以建立起测试机与生产服务器的信任通道,测试机就可以安全地操作生产服务器完成自动部署。

配置

现在我以scp方式部署nodejs应用为例,来说明travis-ci做自动部署的配置。

首先,建立起开发机与生产服务器的信任关系:

ssh-copy-id username@host

然后,加密你的私钥,私钥文件通常在~/.ssh/id_rsa。加密私钥文件需要使用travis这个命令行工具,它是一个ruby包,使用gem安装:

gem install travis
travis login

输入账号密码登录成功后,使用travis encrypt-file加密:

travis encrypt-file ~/.ssh/id_rsa --add

上面命令执行完后,会生成一段解密命令并添加到.travis.yml中:

before_install:
 - openssl aes-256-cbc -K $encrypted_830d3b21a25d_key -iv $encrypted_830d3b21a25d_iv
 -in ~/.ssh/id_rsa.enc -out ~/.ssh/id_rsa -d

接下来,把加密后的私钥文件(id_rsa.enc)复制到代码库中,千万要注意不要错把未加密的私钥文件(id_rsa)复制到你的代码库中。然后把上面的解密命令的-in ~/.ssh/id_rsa.enc改为-in id_rsa.enc

通过上面的过程就基本建立测试机与生产服务器的信任关系,但还有一些小细节要处理。例如,降低id_rsa文件的权限,否则ssh处于安全方面的原因会拒绝读取秘钥;将生产服务器地址加入到测试机的信任列表中,否则连接时会询问是否信任服务器。更改后的配置如下:

before_install:
 - openssl aes-256-cbc -K $encrypted_830d3b21a25d_key -iv $encrypted_830d3b21a25d_iv
 -in id_rsa.enc -out ~/.ssh/id_rsa -d
 - chmod 600 ~/.ssh/id_rsa
 - echo -e "Host 102.201.64.94\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

最后,测试机就可以愉快地操作生产服务器了,例如下面是一个nodejs应用的.travis.yml文件配置:

language: node_js
node_js:
 - '4.4.4'
before_install:
 - openssl aes-256-cbc -K $encrypted_830d3b21a25d_key -iv $encrypted_830d3b21a25d_iv
 -in id_rsa.enc -out ~/.ssh/id_rsa -d
 - chmod 600 ~/.ssh/id_rsa
 - echo -e "Host 102.201.64.94\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
script:
 - npm run test
after_success:
 - npm prune --production # 删除devDependencies
 - tar -jcf indoor-server.tar.bz2 * # 打包并压缩代码
 - scp indoor-server.tar.bz2 jingsam@102.201.64.94:~/ # 复制到生产服务器上
 - ssh jingsam@102.201.64.94 'mkdir -p indoor-server && tar -jxf indoor-server.tar.bz2 -C indoor-server' # 解压
 - ssh jingsam@102.201.64.94 'cd indoor-server && pm2 startOrReload pm2.json' # 重启pm2

总结

本篇文章讲的自动部署其实与nodejs关系不大,完全适用于各种语言的自动部署,其原理都是相通的。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持

Javascript 相关文章推荐
jQuery 1.0.2
Oct 11 Javascript
!DOCTYPE声明对JavaScript的影响分析
Apr 12 Javascript
设为首页和收藏的Javascript代码(亲测兼容IE,Firefox,chrome等浏览器)
Nov 18 Javascript
Jquery 获取对象的几种方式介绍
Jan 17 Javascript
requirejs按需加载angularjs文件实例
Jun 08 Javascript
webpack教程之webpack.config.js配置文件
Jul 05 Javascript
chorme 浏览器记住密码后input黄色背景处理方法(两种)
Nov 22 Javascript
JavaScript作用域、闭包、对象与原型链概念及用法实例总结
Aug 20 Javascript
详解Vue中watch的详细用法
Nov 28 Javascript
JavaScript惰性求值的一种实现方法示例
Jan 11 Javascript
JS实现前端动态分页码代码实例
Jun 02 Javascript
适用于 Vue 的播放器组件Vue-Video-Player操作
Nov 16 Javascript
Vue框架中正确引入JS库的方法介绍
Jul 30 #Javascript
webpack配置sass模块的加载的方法
Jul 30 #Javascript
Angular.js中$resource高大上的数据交互详解
Jul 30 #Javascript
Vue的Flux框架之Vuex状态管理器
Jul 30 #Javascript
webpack实现热加载自动刷新的方法
Jul 30 #Javascript
利用JavaScript如何查询某个值是否数组内
Jul 30 #Javascript
Angular.js中上传指令ng-upload的基本使用教程
Jul 30 #Javascript
You might like
php无限分类且支持输出树状图的详细介绍
2013/06/19 PHP
Laravel 前端资源配置教程
2019/10/18 PHP
laravel框架中路由设置,路由参数和路由命名实例分析
2019/11/23 PHP
Alliance vs Liquid BO3 第二场2.13
2021/03/10 DOTA
用javascript动态调整iframe高度的方法
2007/03/06 Javascript
JavaScript 面向对象编程(2) 定义类
2010/05/18 Javascript
js制作的鼠标悬浮时产生的下拉框效果
2012/10/27 Javascript
两种方法实现在HTML页面加载完毕后运行某个js
2014/06/16 Javascript
javascript实现检验的各种规则
2015/07/31 Javascript
javascript运动效果实例总结(放大缩小、滑动淡入、滚动)
2016/01/08 Javascript
JavaScript DOM 对象深入了解
2016/07/20 Javascript
a标签跳转到指定div,jquery添加和移除class属性的实现方法
2016/10/10 Javascript
通过网页查看JS源码中汉字显示乱码的解决方法
2016/10/26 Javascript
vue中echarts3.0自适应的方法
2018/02/26 Javascript
js input输入百分号保存数据库失败的解决方法
2018/05/26 Javascript
vue中使用input[type="file"]实现文件上传功能
2018/09/10 Javascript
vue项目中,main.js,App.vue,index.html的调用方法
2018/09/20 Javascript
javascript设计模式 ? 适配器模式原理与应用实例分析
2020/04/13 Javascript
jQuery三组基本动画与自定义动画操作实例总结
2020/05/09 jQuery
python使用自定义user-agent抓取网页的方法
2015/04/15 Python
详解详解Python中writelines()方法的使用
2015/05/25 Python
python scp 批量同步文件的实现方法
2019/01/03 Python
Python 实现中值滤波、均值滤波的方法
2019/01/09 Python
django 实现将本地图片存入数据库,并能显示在web上的示例
2019/08/07 Python
Django 自定义分页器的实现代码
2019/11/24 Python
python实现快递价格查询系统
2020/03/03 Python
opencv 图像礼帽和图像黑帽的实现
2020/07/07 Python
python简单实现插入排序实例代码
2020/12/16 Python
Ootori在线按摩椅店:一家专业的按摩椅制造商
2019/04/10 全球购物
澳大利亚美容产品及化妆品在线:Activeskin
2020/06/03 全球购物
PatPat香港:婴童服饰和亲子全家装在线购物
2020/09/27 全球购物
新闻传媒系求职信范文
2014/04/19 职场文书
2014年办公室人员工作总结
2014/12/09 职场文书
幼儿园托班开学寄语(2015秋季)
2015/05/27 职场文书
golang中实现给gif、png、jpeg图片添加文字水印
2021/04/26 Golang
奥特曼十大神器:奥特手镯在榜,第一是贝利亚的神器
2022/03/18 日漫