上一篇文章初步介绍了如何用docker+jenkins自动部署前端项目,但实际开发过程中,安装jenkins的机器一般和部署服务器是分离的,一般是一台安装jenkins的机器负责n个项目的部署,本篇文章介绍如何将前端(VUE)项目部署到远程服务器上,实际上是多了ssh连接远程服务器的过程,本文演示用到了阿里云服务器(各个厂商的云服务器大同小异)和本地安装了docker+jenkins的机器(上篇文章已经介绍了如何安装docker+jenkins)。
整体步骤:
获取源代码
本文依然拿github试手,过程与上篇文章一致, 测试github地址:github.com/marco110/do… ,全部脚本都在此项目中。
打包代码并构建镜像
脚本同上篇文章基本一致。
镜像推送到阿里云镜像仓库
此过程涉及到了阿里云账号的问题,我已经在阿里云镜像服务创建了个人实例,仓库名称为image-test,命名空间为marco_images,点击‘images-test’进入镜像仓库基本信息,该页面介绍了如何登录阿里云Docker Registry,如何拉取和推送镜像。
开始改造我们的Jenkinsfile,github已提供了完整脚本。
node() {
// 个人阿里云镜像仓库地址及命名空间
def registry = 'registry.cn-beijing.aliyuncs.com'
def aliyunNamespace = 'marco_images/image-test'
...
// 构建并上传镜像到阿里云
stage('build & upload Image') {
withCredentials([usernamePassword(credentialsId: 'jenkins_login_aliyun_docker', usernameVariable: 'username', passwordVariable: 'password')]) {
try {
sh 'cp -r dist ./devops_build'
// 登录到阿里云Docker Registry
sh "docker login -u ${username} -p ${password} ${registry}"
sh "docker build -t ${registry}/${aliyunNamespace} ./devops_build"
sh "docker tag ${registry}/${aliyunNamespace} ${registry}/${aliyunNamespace}:${dockerTag}"
// 推送到阿里云镜像仓库
sh "docker push ${registry}/${aliyunNamespace}:${dockerTag}"
// 删除本地镜像
sh "docker rmi ${registry}/${aliyunNamespace}:${dockerTag}"
}
catch(err) {
echo "build and upload Image failed"
throw err
}
}
}
}
注意到我们脚本里面有 withCredentials([usernamePassword(credentialsId: 'jenkins_login_aliyun_docker', usernameVariable: 'username', passwordVariable: 'password')]),没错,这就是需要你的阿里云账户名和密码,像这么敏感信息肯定不会直接暴露在代码里,需要我们在jenkins页面配置。进入jenkins页面,点击进入我们的项目添加凭据,我直接添加为了全局凭据,注意id需要和我们Jenkinsfile中填写的一致。当脚本运行到此处时,就会发现自己的阿里云容器仓库->镜像版本中多了一条记录,此时我们已经成功的把镜像推送到了云端!
连接远程服务器,拉取镜像并运行容器
此时镜像已经在云端了,需要连接的远程项目部署服务器,上一篇文章我们安装了jenkins SSH Pipeline Steps插件,从名字我们就能看出是为了连接远程服务器的,继续改造我们的Jenkinsfile。
我们在连接远程服务器时,getServer方法中又出现了withCredentials([usernamePassword(credentialsId: 'ssh_remote_server', passwordVariable: 'password', usernameVariable: 'username')]), 同样需要我们添加凭据,输入远程服务器的账户名和密码。
此时我将远程服务器ip直接放在了脚本中,感觉此做法不对,希望有大神指点!
node() {
// 部署项目的服务器ip
def sshIP = 'xxx.xxx.xxx.xxx'
def dockerName = 'marco-test'
stage('ssh server & pull image'){
try {
// 连接远程服务器
def sshServer = getServer(sshIP)
// 更新或下载镜像
sshCommand remote: sshServer, command: "docker pull ${registry}/${aliyunNamespace}:${dockerTag}"
// 停止并删除容器
sshCommand remote: sshServer, command: "docker rm -f ${dockerName}"
// 启动
sshCommand remote: sshServer, command: "docker run -u root --name ${dockerName} -p 80:80 -d ${registry}/${aliyunNamespace}:${dockerTag}"
// 只保留3个最新的镜像
sshCommand remote: sshServer, command: """docker rmi -f \$(docker images | grep ${registry}/${aliyunNamespace} | sed -n '4,\$p' | awk '{print \$3}') || true"""
}
catch(err){
echo "remote & pull image failed"
throw err
}
}
}
def getServer(ip){
def remote = [:]
remote.name = "server-${ip}"
remote.host = ip
remote.port = 22
remote.allowAnyHosts = true
withCredentials([usernamePassword(credentialsId: 'ssh_remote_server', passwordVariable: 'password', usernameVariable: 'username')]) {
remote.user = "${username}"
remote.password = "${password}"
}
return remote
}
大功告成
此时访问ip:80 就能看到你发布的网站了。
如有失败,务必先去看错误信息,不要盲目的百度!此过程需要jenkins插件的支持,同上篇文章提到的Docker Pipeline、SSH Pipeline Steps、CloudBees Docker Build and Publish。
此篇依旧是为了记录过程,在下也是初识docker和jenkins,在这方面并不专业,如有错误,欢迎指出。