前言
最近了解了一番持续集成、持续交付、持续部署相关。个人对此的相关理解也再说下。
现在很多大型公司的开发流程较为成熟完善,基本都需要做自动化相关,而docker就能很方便地配合各种自动化框架(jenkins、travis)进行自动化集成、部署、运行等。
关于持续集成、持续交付、持续部署等概念,这里个人简单做一下阐述
持续集成:以前是多个开发测试完毕后,才把代码往主分支上合并,可能交叉、冲突,合并之后还可能产生新的问题。而持续集成,就是经常提交代码到主分支,一天可能好几次。并且,自动化地进行单元测试并提供测试报告等,这样的话就能拆分细度颗粒,保证产品能够一步一步地安全可靠地迭代。很多以测试驱动开发的公司就是这样做的。
持续交付:持续集成的基础上,增加打包构建形成产物。
持续部署:持续交付的基础上,增加部署到相应的线上环境。
总而言之,这些持续做的事情,就是为了经常提交代码自动化测试、运行、部署,反馈问题,解决问题,再测试、运行、部署依次循环。持续部署还有个好处,对我们个人网站来说,我们可以直接提交代码,后续一系列过程都是自动化的,就不用管了,它自己自动部署发布。
关于jenkins和travis,jenkins是我个人比较推荐的,因为它生态好、插件环境强、历史悠久、稳定;而travis,个人主要是练手尝试,他可以直接与github互联,而我的代码也是放在github上的,所以直接试试它。
GPS定位系统系列
收获
学习完这篇文章你将收获:
- 无密ssh登录服务器
- travis构建
- 阿里云容器镜像服务
- docker-compose
- travis.yml脚本逻辑
- 持续部署相关
[TOC]
正题
大体流程:
提交代码->触发github的hooks钩子->travis自动触发->依照.travis.yml构建环境,执行脚本->完成部署
脚本大体逻辑:
1、travis openssl加密访问服务器的私钥,生成加密文件xxx.enc,在travis中解密形成其本地密钥
2、项目maven打包
3、docker构建生成镜像
4、发布镜像到阿里云容器镜像
5、ssh访问服务器(利用解密后的本地[指travis运行环境]密钥),执行docker-compose完成部署
开发逻辑:
1、绑定travis和github
2、无密登录ssh,本地项目安装travis,加密密钥
3、阿里云开通容器镜像服务
4、添加.travis.yml和Dockerfile文件
5、提交代码
一、绑定travis和github
注意,travis现在有两个网站,https://www.travis-ci.org和https://www.travis-ci.com
千万不要搞混了,org的是免费的,对于github的开源项目免费,com是收费的,不过对private的项目有构建次数的限制。(我之前就是没有注意org还是com,结果发现,项目构建,一直出问题,iv nodefined
就是因为,add密钥的解密环境变量到org去了,而com下面没有,所以构建失败,如图)
1)直接sign in使用github账号登录,并授予权限
image-202007171108444172)勾选开启你要构建的项目 即可
二、无密登录ssh,本地项目安装travis,加密密钥
按道理,一般自己都有了id_rsa和id_rsa.pub的密钥,路径在~/.ssh/
下,这里我们再单独新建一个没有密码的密钥
1)生成无密密钥
cd ~/.ssh
ssh-keygen -t rsa
第一次输入的是文件名:nopwd
第二次、第三次都输入密码,我们是无密码,所以直接回车
这样就生成好了密钥对,nopwd(私钥)和nopwd.pub(公钥)
2)上传公钥到服务器
sh-copy-id -i ~/.ssh/nopwd.pub root@你的服务器地址
3)安装travis
换源
gem sources -l
gem sources --add https://gems.ruby-china.org/ --remove
安装
sudo gem install travis
切换到项目目录下
travis init
可能出现构建失败,安装依赖ruby-dev
sudo apt install ruby-dev
4)使用github账号登录travis
travis login --auto
如果本地有token或者github密钥的话,就能直接登录。不然,就输入账号密码
5)加密密钥
travis encrypt-file ~/.ssh/nopwd --add
--add
会提示让你加入一段解密密钥的脚本到.travis.yml
文件中,如果有文件就会添加到文件里,没有文件它给你创建或者你自己创建(travis init就会自动创建)。
before_install: - openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv -in nopwd.enc -out ~/.ssh/nopwd -d
这就是要加入的内容,-out ~/.ssh/xxx 这里你可以自己去名字,默认是id_rsa,后面ssh登录服务器会用到
其中encrypted_d51746e9182b_iv就是用来解密的
注意,这里travis会上传两个环境变量encrypted_d51746e9182b_iv到服务器后台去
image-20200717112521822当然,环境变量的好处就是,你可以把.tavis.yml里面会用到的变量,都到这里来控制。
比如,你的addons添加的ip地址,就可以这里来定义,然后文件里,就$ip来使用。这样,如果ip地址有变动,直接修改一下配置就可以了。
三、阿里云开通容器镜像服务
阿里云 产品与服务中 找到【容器镜像服务】然后,添加镜像。当然你也可以使用dockerhub来进行镜像的管理,不过速度可能没有国内的阿里云快。
这里我是web前端一个,java后端一个。
每个容器都可以管理不同版本的镜像文件。
image-20200717112833270 image-20200717112936933好了,之后就有相关的文档供配置使用。
四、添加.travis.yml和Dockerfile文件
java后端项目配置
Dockerfile
在项目根目录下,创建Dockerfile(以前在服务器端创建过,这里直接放到项目中来了)
# FROM adoptopenjdk/openjdk8:ubi
# openj9内存会小很多
FROM adoptopenjdk:8-jdk-openj9
VOLUME /tmp
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
逻辑大致为:拉取jdk镜像,拷贝项目生成的jar包到容器,运行jar包
.travis.yml
language: java
services:
- docker
sudo: required
branches:
only:
- master
#使用ssh登陆的时候会确认主机信息,travis-ci自动化运行无法进行交互操作,所以在.travis.yml中添加以下内容跳过确认
addons:
ssh_known_hosts: $server_ip
before_install:
- openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv
-in nopwd.enc -out ~/.ssh/nopwd -d
script:
- mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest .
after_success:
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
- chmod 600 ~/.ssh/nopwd
- ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@$server_ip "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
使用ssh登陆的时候会确认主机信息,travis-ci自动化运行无法进行交互操作,所以在.travis.yml中添加,
这里我们使用环境变量来控制,避免写死。环境变量,在travis的后台settings里面添加
addons:
ssh_known_hosts: $server_ip
-t
后面则是你阿里云容器的镜像地址,可以设置版本,这里直接使用latest最新版
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest .
登陆阿里云容器镜像,并推送镜像
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
这里跟文档上有点不同,你可以直接-p
加入你自己的密码,就不用输入了,密码也是环境变量来配置aliyun_pwd
密钥文件可能没有权限,给予权限
chmod 600 ~/.ssh/nopwd
ssh登录服务器,执行docker-compose拉取镜像,开启服务
ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@47.108.82.91 "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
-i ~/.ssh/nopwd
使用travsi系统中的密钥登录
docker-compose.yml
version: '2'
services:
mysql:
container_name: mysql1
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: 数据库密码
ports:
- "3306:3306"
volumes:
- /usr/local/docker/mysql/data:/var/lib/mysql
- /usr/local/docker/mysql/conf:/etc/mysql
- /usr/local/docker/mysql/logs:/var/log/mysql
web:
container_name: jafir_nginx1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest
ports:
- 8080:80
restart: always
depends_on:
- java
volumes:
- /mydockerdata/nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- /mydockerdata/nginx/log/:/var/log/nginx
java:
container_name: jafir_gps1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-images:latest
restart: always
depends_on:
- mysql
ports:
- 9090:9090
volumes:
- /mydockerdata/java/gps/upload:/Users/jafir/Downloads/upload
- /mydockerdata/arme/out/*.nofoo.cn/*.nofoo.cn.pfx:/Users/jafir/Downloads/upload/cert/*.nofoo.cn.pfx
我们这里直接使用docker-compose来启动3个服务,方便快捷。当然,你也可以单独启动java一个容器。
逻辑也比较清晰
完成后提交代码即可,不出意外的话就触发travis的构建,服务也能够启动起来啦。
image-20200717115550739vue前端项目配置
Dockerfile
在项目根目录下,创建Dockerfile
FROM nginx
COPY dist/ /usr/share/nginx/html/
逻辑大致为:拉取镜像,拷贝项目静态文件到nginx容器内默认的目录
.travis.yml
language: js
services:
- docker
sudo: required
branches:
only:
- gps
addons:
ssh_known_hosts: $server_ip
before_install:
- openssl aes-256-cbc -K $encrypted_d51746e9182b_key -iv $encrypted_d51746e9182b_iv
-in nopwd.enc -out ~/.ssh/nopwd -d
script:
- npm run build
- docker build -t registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest .
after_success:
- docker login --username=jafir@1866908499405822 -p=$aliyun_pwd registry.cn-hangzhou.aliyuncs.com
- docker push registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/jafir-web:latest
- chmod 600 ~/.ssh/nopwd
- ssh -o "StrictHostKeyChecking no" -i ~/.ssh/nopwd root@$server_ip "cd /mydockerdata;docker-compose -f docker-compose.yml pull;docker-compose -f docker-compose.yml up -d;exit"
主要逻辑与上面的几乎一致。
不过要注意一点:
以往我们都是通过上传到服务器的dist目录,再映射到 /usr/share/nginx/html
去的。而现在是,直接把代码打包到镜像里面去,所以,不需要再映射了,不然的话就会映射一个空目录进去了。
web:
container_name: jafir_nginx1
image: registry.cn-hangzhou.aliyuncs.com/jafir_docker_images/web:latest
ports:
- 8080:80
restart: always
depends_on:
- java
volumes:
- /mydockerdata/nginx/etc/nginx.conf:/etc/nginx/nginx.conf
- /mydockerdata/nginx/log/:/var/log/nginx
volumes是只有配置文件的映射的,不需要项目目录的映射。
五、提交代码,成功
随意提交一下代码,就能看到服务器的docker-compose的项目启动起来啦!
travis的控制台也能看到构建成功啦。
image-20200717125015731关于作者
作者是一个热爱学习、开源、分享,传播正能量,喜欢打篮球、头发还很多的程序员-。-
热烈欢迎大家关注、点赞、评论交流!
简书:https://www.jianshu.com/u/d234d1569eed
github:https://github.com/fly7632785
网友评论