实现思路

使用springboot自带的mvnw编译
使用Github实现项目版本管理
travis监测到代码push后,使用项目自带的mvnw编译打包springboot项目成jar包
再在travis内登录dockerhub,使用项目目录下的Dockerfile打包成镜像上传
travis再通过ssh远程连接生产环境服务器,使用Docker-compose删除旧容器镜像,重新拉取新镜像并启动容器

一、新建一个Springboot项目

略,并加入一个Dockerfile到项目目录中,后期打包成镜像时需要
Dockerfile:

  1. FROM openjdk:8-jre
  2. #FROM openjdk:8-jre-alpine
  3. LABEL maintainer="1040629819@qq.com"
  4. # 修改时区
  5. RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
  6. RUN mkdir -p /unknwhale
  7. WORKDIR /unknwhale
  8. ARG JAR_FILE=target/*.jar
  9. COPY ${JAR_FILE} app.jar
  10. ENTRYPOINT ["java","-jar","./app.jar","&"]

二、在github开一个仓库做项目版本管理

略,travis对开源项目提供免费支持,如果github有教育包,那么Travis-ci也提供对私有项目的免费。

三、准备一个Travis-ci账号

注册略,.org只支持开源项目(免费),.com支持私有项目(私有项目如果有教育包可以免费)
然后绑定github账号,绑定项目。
如果github有教育包,那么Travis-ci提供对私有项目的免费。

四、新增一个.travis.xml文件

在项目主目录新建一个.travis.xml文件
并在里面填入

  1. # .travis.xml
  2. language: java

push代码,可以在travis网站里看到已经项目开始构建编译测试了

五、让travis可以无密登录ssh连接生产服务器

在生产服务器新建一个travis连接专用账号,通过vi /etc/sudoers在root ALL=(ALL)ALL后新增一行[账号名] ALL=(ALL)ALL给travis账号提供sudo权限(或者可以尝试增加一个adm组,然后给这个组增加sudo权限,然后把travis用户加入到该组)
接着使用ssh-keygen创建公钥与私钥对并加密(此处可以使用开发环境而不是生产环境,加公钥可以使用指令远程加到生产环境),将公钥代码追加到travis用户.ssh文件夹内authorized_keys文件后面。
再安装一个travis,用于加密即将存在仓库中的私钥文件,但在安装travis之前需要安装Ruby(2.4以上):
语雀内容
成功安装ruby后安装travis

  1. sudo gem install travis

然后登陆travis,登陆travis需要登陆github,所以在登陆前先去github申请一个travis登陆用token
拿到后使用travis login --pro --github-token XXXXXXX登陆travis
成功登陆后执行travis encrypt-file ~/.ssh/id_rsa --add加密私钥(—add参数会加入一段解密密钥的脚本到当前目录下的.travis.xml文件中,如果没有travis会自动生成一个.travis.xml文件,不过我实际使用时没加—add参数,而是手动加入的解密脚本到.travis.xml文件中的),加密后会自动在travis网站的项目环境变量中新增两个用于解密的变量
image.png

  1. before_install:
  2. - openssl aes-256-cbc -K $encrypted_f217180e22ee_key -iv $encrypted_f217180e22ee_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d

这就是解密秘钥用的脚本

六、准备dockerhub仓库存放项目镜像

七、在生产环境准备好docker-compose.yml

docker-compose.yml:

  1. version: '3.8'
  2. services:
  3. mysql: # 服务的名称
  4. restart: always # 代表只要Docker启动,那么这个容器就跟着一起启动
  5. image: mysql:8.0.22 # 指定镜像版本
  6. container_name: unknwhale_mysql # 指定容器名称
  7. volumes: # 映射数据卷
  8. - /opt/docker/unknwhale_mysql/conf:/etc/mysql
  9. - /opt/docker/unknwhale_mysql/logs:/var/log/mysql
  10. - /opt/docker/unknwhale_mysql/data:/var/lib/mysql
  11. - /opt/docker/unknwhale_mysql/mysql-files:/var/lib/mysql-files
  12. ports:
  13. - 3306:3306 # 指定端口号的映射
  14. environment:
  15. MYSQL_ROOT_PASSWORD: MyPassWord # 指定MySQL的ROOT用户登录密码
  16. MYSQL_DATABASE: unknwhale
  17. TZ: Asia/Shanghai # 指定时区
  18. java:
  19. container_name: unknwhale-backend
  20. # image: registry.cn-beijing.aliyuncs.com/unknwhale/unknwhale-backend:latest
  21. image: matthewsmark/unknwhale-backend:latest
  22. # image: unknwhale-backend:latest
  23. restart: always
  24. # build:
  25. # context: ./
  26. # dockerfile: Dockerfile
  27. depends_on:
  28. - mysql
  29. ports:
  30. - 8080:8080

八、修改travis文件并push(核心)

  1. # travis编译环境需要sudo权限
  2. sudo: required
  3. # 表示是java项目
  4. language: java
  5. # travis编译环境为linux
  6. os: linux
  7. # travis编译环境使用ubuntu的xenial版本
  8. dist: xenial
  9. # 启用docker服务
  10. services:
  11. - docker
  12. # 只对master分支启用
  13. branches:
  14. only:
  15. - master
  16. before_install:
  17. # 给mvnw文件添加执行权限
  18. - chmod +x mvnw
  19. # 解密秘钥(请自行修改)
  20. - openssl aes-256-cbc -K $encrypted_f217180e22ee_key -iv $encrypted_f217180e22ee_iv -in .travis/id_rsa.enc -out ~/.ssh/id_rsa -d
  21. # 修改私钥权限,以免被ssh拒绝连接
  22. - chmod 600 ~/.ssh/id_rsa
  23. addons:
  24. # 把生成环境ip添加到ssh已知ip中(不知道有什么用)
  25. ssh_known_hosts: $server_ip
  26. before_script:
  27. # 修改项目jar包的权限为777,以免出现进入docker镜像后却无法运行的问题
  28. - chmod 777 ./target/*.jar
  29. # 使用当前目录下的Dockerfile构建镜像并tag
  30. - docker build -t matthewsmark/unknwhale-backend:latest .
  31. # - docker build -t registry.cn-beijing.aliyuncs.com/unknwhale/unknwhale-backend:latest .
  32. script:
  33. # 此处用于测试项目
  34. - echo "now is testing"
  35. # 测试成功后
  36. after_success:
  37. # 登录docker
  38. - echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin
  39. # - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin registry.cn-beijing.aliyuncs.com
  40. # - docker login --username=$DOCKER_USERNAME -p=$DOCKER_PASSWORD registry.cn-beijing.aliyuncs.com
  41. # push新镜像
  42. - docker push matthewsmark/unknwhale-backend:latest
  43. # - travis_wait 60 docker push registry.cn-beijing.aliyuncs.com/unknwhale/unknwhale-backend:latest
  44. # 使用ssh连接生产环境
  45. # 因为执行过程较长,避免travis过10钟超时退出,我们使用travis_wait 60来让travis给他60分钟的执行时间
  46. # cd /opt/projects/unknwhale/backend/ 进入项目目录
  47. # echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin 登录docker
  48. # docker-compose down;docker rmi $(docker images -f "dangling=true" -q);docker rmi matthewsmark/unknwhale-backend:latest 使用docker-compose关闭并删除容器,接着删除none镜像与旧的项目镜像
  49. # docker-compose up -d --build;exit;重新拉取新镜像并启动容器,然后退出ssh
  50. - travis_wait 60 ssh -o StrictHostKeyChecking=no root@$server_ip "cd /opt/projects/unknwhale/backend/;echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin;docker-compose down;docker rmi $(docker images -f "dangling=true" -q);docker rmi matthewsmark/unknwhale-backend:latest;docker-compose up -d --build;exit;"
  51. # - travis_wait 60 ssh -o StrictHostKeyChecking=no root@$server_ip "cd /opt/projects/unknwhale/backend/;echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin;docker-compose down --rmi all;docker-compose up -d --build;exit;"
  52. # - ssh travis@$server_ip "cd /opt/projects/unknwhale/backend/;docker login --username=$DOCKER_USERNAME -p=$DOCKER_PASSWORD registry.cn-beijing.aliyuncs.com;docker-compose stop;docker-compose up -d --build;"

修改后push代码到master分支,可以在travis官网看到CI/CD的全程log

参考文档