gitlab-runner docker基于sftp实现项目CI/CD自动部署
最近在给单位组建了CI/CD,要求对开发人员git的代码进行build和deploy,第一次从头研究CI/CD,真的踩了不少坑,尤其是deploy部分,卡了我三天了。
起因
环境:
ubuntu物理机专门做CI/CD工具机,已经使用了docker-compose同时安装了gitlab和gitlab-runner
gitlab用于代码托管,gitlab-runner用于run gitlab-ci,实现自动编译,测试,部署一步到位
一台远程的WEB服务器,生产环境
问题:
由于gitlab-runner是在docker下跑的,而gitlab-runner使用的执行环境也是docker,这就导致一个问题,编译后的文件无法直接拷贝到物理机,docker是个完全隔离的沙盒,docker也会在结束CI/CD后立马销毁,好在在docker CI/CD任务没有完成前,我们是可以获得build的文件的。
如何把需要部署的文件,例如jar,bin包部署到服务器呢?我思考了很多种方案:
- 使用
scp
复制到远程,失败:需要账号密码,gitlab-ci都不给你机会输入 - 使用
sshpass
+scp
,可以条过密码,但过程繁琐,而且还是出现了权限问题,没深入 - 使用
ftp
,由于ftp这个老东西无论是被动模式还是主动模式对双方开放随机端口,我觉得不安全,放弃 - 使用
rsync
,要同时配置服务端,客户端,真的很麻烦,都不想看 - 最后决定使用
sftp
,利用了服务器自带的ssh用户(需要新建安全的用户,指定目录) - jekenis,这个很强大,也很重,需要较长学习周期,部署各种服务,但我方项目较小,暂不考虑,优先考虑轻量级的sftp
以上都是我参考了大量在线的文档,博客,最后总结了一套自己的docker下sftp deploy方法
这里用node下vue项目举例,比如build过后的vue项目会产生一个dist目录,我现在要把这个下面所有的文件都发布到web服务器上!
开始
首先,你需要先把runner添加到gitlab才能run呀,这个在上两篇docker-compose搭建gitlab的文章中讲述过,这里在提醒下:gilab打开项目,左边菜单栏,Settings-》CI/CD,下拉runner,找到url和token,通过gitlab-runner register注册进去,注册完,就可以看到新的runner显示绿色可用状态。
下一步,你需要写gitlab-ci.yml和deploy.sh,当然你也可以一并写到gitlab-ci.yml中。我分开了,因为我喜欢写shell!
我的.gitlab-ci.yml
stages:
- build
- deploy
cache:
key:
files:
- package.json
paths:
- node_modules
build:
stage: build
before_script:
- npm config set registry https://registry.npm.taobao.org
script:
- npm install
- npm run build
artifacts:
expire_in: 1 day
paths:
- dist
deploy:
stage: deploy
image: ubuntu:20.04
before_script:
- rm /etc/apt/sources.list
- echo 'deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse' >> /etc/apt/sources.list
- echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse' >> /etc/apt/sources.list
- echo 'deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse' >> /etc/apt/sources.list
- mkdir ~/.ssh
- echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >~/.ssh/config
- 'which lftp || ( apt-get update -y && apt-get install lftp -y )'
script:
- bash ./deploy.sh
关于gitlab-ci这个yml脚本,我必须特别说明下,里面有很多精华是我踩了很多的坑才写出来的。
下面是一篇官方文档:
Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD
重点在before_script里面:
- 首先你需要更换ubuntu的apt源到国内,提高速度,否则CI/CD很慢!
- 把npm也换到国内,否则也很慢!
- 然后你需要关闭ssh验证,这个很繁,docker下的runner系统每次都会问(每次run都是一个新环境),但你无法输入yes,所以你必须关闭StrictHostKeyChecking,否则失败。在你本地一般不会报错,原因是你看看.ssh下的kownhosts阿!你已经允许过了!
- 安装lftp,用这个工具上传到sftp!很方便!
deply.sh
#!/bin/bash
#指定对端FTP服务器的用户名和密码
USER="xxxx"
PASSWD="xxxx"
IP='xxx.xxx.xxx.xxxx'
P='22'
DIR='example.com'
targetDay=$(date -d "-1 days" +"%Y-%m-%d")
lftp -u $USER,$PASSWD sftp://$IP:$P <<EOM
mirror -R dist $DIR
bye
EOM
[ $? -eq 0 ] && echo "Upload SFTP server successful [$targetDay]"
这里这个deploy.sh其实是可以合并到yml里的,因为gitlab-ci.yml本来就是shell脚本的简化而以,用了gitlab-ci就不必要单独写shell,这里独立出来对我来说更加清晰,我解释下里面内容:
- 首先定义连接sftp服务器的变量,用户名,密码阿之类的。这些以后要放到gitlab-runner的variables里更安全,不然提交git的人都知道部署生产服务器的账户密码了,在大公司里是绝对不可以的。
- 关于上一条里的用户,肯定是不建议用root的,可以useradd新建一个用户,把www目录分配给他,我新建了一个deploy用户,最好再把网站deploy目录也
chmod 777
一下,不然还可能会有“permission denied”问题 - lftp里面上传的是整个目录,要用
mirror
命令!注意不是put
, 也不能用所谓的put -r
,这都是坑阿,坑的我哭了。
一看job succeed,甚是激动,终于从坑里爬出来了。