工做中,除了开发功能,还负责系统的部署工做。我从频繁的部署工做中,逐渐找到了一些偷懒的方法。从传统的Java -jar命令启动服务,到经过Docker 容器构建部署服务,再后来经过自动化部署工具Jenkins来完成部署,最后再结合Ansible完成远程部署。一步步的进步极大的减小部署工做,提升了工做效率(增长了许多划水时间)。前端
Docker 是一个开源的应用容器引擎,让开发者能够打包他们的应用以及依赖包到一个可移植的容器中,而后发布到任何流行的 Linux机器上,也能够实现虚拟化,容器是彻底使用沙箱机制,相互之间不会有任何接口。
Docker给个人印象很深,没有什么环境是docker pull 解决不了的,java
docker ps , docker ps 默认显示运行中的容器,-a 显示全部,-l显示近期建立的容器 docker start xxx , 启动xxx容器 docker restart xxx , 重启xxx容器 docker run xxx , 建立并运行xxx容器 docker build -t xxx . ,使用 Dockerfile 建立镜像 docker stop xxx , 关闭容器 docker rm xxx , 删除容器 docker images , 查看全部镜像 docker rmi xxx , 删除xxx镜像 docker exec -it xxx sh , 进入xxx容器中,用quit退出 docker logs -f xxx --tail 500 , 查看xxx容器的日志,显示最后500行,经常使用命令 docker inspect xxxx , 查看容器配置信息 docker-compose -f app.yml up -d , 按照app.yml文件配置以debug形式启动 docker-compose -f app.yml down , 按照app.yml文件配置形式关闭
第一步:在gradle项目加入docker插件,即在gradle.build 文件中加入如下代码。须要注意的有插件的版本,项目打包后的名称,Dockerfile文件目录mysql
dependencies { classpath("se.transmode.gradle:gradle-docker:1.2") } apply plugin: 'docker' task buildDocker(type: Docker, dependsOn: build) { push = false applicationName = "项目名" dockerfile = file('src/main/docker/Dockerfile文件目录') doFirst { copy { from jar into stageDir } } }
第二步:建立Dockerfile文件,文件目录要和第一步中设置的保持一致。须要配置jdk镜像和基本的启动参数spring
FROM frolvlad/alpine-oraclejdk8:slim VOLUME /tmp ADD 项目jar名称.jar app.jar RUN sh -c 'touch /app.jar' ENV JAVA_OPTS="" ENV PORT="6666" ENV DB_CONNECTION="jdbc:mysql://ip:port/database" ENV DB_USER="user" ENV DB_PASSWORD="password" ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar --spring.datasource.url=$DB_CONNECTION --spring.datasource.usernam=$DB_USER --spring.datasource.password=$DB_PASSWORD --port=$PORT"]
第三步:将jar拷贝到服务器上,而后执行编译,运行的docker命令sql
一)、经过gradle的bootJar,将项目打包。同时须要把引入的第三方jar也要一块儿打入到项目jar中。docker
二)、Windows系统中能够经过Xftp将jar和Dockerfile文件拷贝同一个目录下。Linux系统能够经过scp命令上传文件。shell
三)、执行docker ps,查看当前运行的容器,执行docker stop和docker rm 关闭和删除以前旧版本的容器npm
四)、找到jar的目录,并在当前目录下,执行 docker build -t 镜像名称 . 的命令编译项目,注意后面的点不要漏了。后端
五)、编译成功后执行 docker run --name 容器名 -v /tmp:/tmp -p 对外开发的端口:项目启动的端口 镜像名:latest 。启动容器浏览器
六)、执行docker ps,查看容器启动是否正常启动。同时执行docker logs -f 容器名 --tail 500,查看容器启动日志,检查是否有异常
七)、最后浏览器访问一下,已确保部署成功。
全称大概须要几分钟的时间,虽然不算麻烦。可次数多了,就很麻烦了。有没有什么好的工具帮助咱们完成这一系列操做呢?答案是确定的。
The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.
Jenkins 的logo是一个管家的形象,很贴切。对它的理解比较肤浅。他经过管理Git上的项目,来确保每次打包的jar都是最新的。同时在构建成功后执行咱们输入的shell命令,来达到自动化部署的工做。
第一步:建立一个负责编译的Jenkins项目,
在Jenkins控制台页面,点击页面左上角的“新建”按钮。再输入项目名后,能够选择建立一个空项目,也能够在页面最下面选择copy from 其余项目。无论如何建立,咱们须要Jenkins管理项目的源码,构建和构建后的操做。
第二步:建立一个负责运行的Jenkins项目
以一样的方式建立项目,在构建触发器上,选择第一步建立的项目,构建的Shell命令是先删除以前的容器,而后在从新运行容器。若以前的容器不存在,则会构建失败。因此第一次构建的时候把第一行命令删掉。解决方案傻乎乎的,只是由于没有花时间去处理。
第三步:选择编译项目,点击当即构建,当第一个项目构成成功后,会自动触发运行项目。等待两个项目都成功后,就能够访问浏览器,检查功能。
有了Jenkins,一切变得轻松不少。但他也有一个较大的弊端,就是使用前必需要先安装。特别是在客户的服务器上,也许别人就只跑这一个服务,你给别人整了一个Jenkins,彷佛有点大材小用了。有没有好的解决方法?答案是确定的。
Ansible is an IT automation tool. It can configure systems, deploy software, and orchestrate more advanced IT tasks such as continuous deployments or zero downtime rolling updates.
从接触到使用Ansible大概有一天的时间,对它的理解也是比较肤浅。我单纯的认为,他能够帮助咱们在服务器之间传输文件,同时还能够执行一些shell命令。抱着这样的想法,咱们能够经过Jenkins完成自动化编译,再经过Ansible传输资源文件到部署的环境中,同时执行启动Shell命令。
第一步:修改Jenkins运行项目的构建Shell,将以前的docker run改为
ansible-playbook ansible命令文件路径/app.yaml
第二步:建立Ansible脚本文件app.yaml,目录和第一步中设置的保存一致,模版大体以下
- hosts: '须要部署的远程服务ip' tasks: - name: "关闭旧版本的容器" shell: docker stop xxx ignore_errors: true - name: "删除旧版本的容器" shell: docker rm xxx ignore_errors: true - name: "删除以前的旧文件" shell: rm -rf /旧文件路径/* - name: "传输Dockerfile文件" copy: src=/文件目录/Dockerfile dest=/远程服务指定目录 - name: "传输Jar文件" copy: src=/jar目录/xxx.jar dest=/远程服务指定目录 - name: "构建docker 镜像" shell: chdir=/jar所在目录 nohup docker build -t 镜像名 . - name: "启动容器" shell: nohup docker run --name 容器名 -v /挂载路径/:/挂载路径/ -p 对外端口:服务端口 -d 镜像名:latest
第三步:在Jenkins上构建编译项目。
到这里,三种部署的流程就完成了。若是你熟悉Docker的方式构建,再用Jenkins和Ansible的时候,就会简单不少。我在实际开发中,项目是先后端分离的。公司作了两个方案,
第一种:先后端分开部署,即Jenkins上有四个项目。前端和后端各两个项目。这样的好处就是先后端互不影响。不会由于对方的错误而重新编译。缺点也是有的,很难保证对方部署的环境是最新的。
第二种:把先后端放在一个项目中,一次构建完成两个项目的打包部署。缺点是构建慢,优势就是保证两端的代码都是最新的,适合发布到预发布环境和正式环境。
那么,针对先后端一块儿部署的需求,Jenkins和Ansible一样也须要简单的修改。其思路就是Jenkins负责编译项目,将资源文件压缩,再经过Ansible上传到其余服务器上。执行解压,构建,启动的命令。
看起来视乎很简单,但有一个坑但愿大家跨过去。前端打包须要npm或者其余工具,可是你的服务器上没有安装。此时请务必经过Jenkins控制台,或者用Jenkins账号登陆服务器安装这些工具。笔者就是经过root账号登陆服务器安装的npm,经过Jenkins编译时提示没有权限。