需求
因为要基于Gitlab的基础上去做一个每当有仓库push的时候会自动触发Docker自动打包Image的功能,Gitlab有System Hooks功能,System Hooks简单来说就是可以定义每当有仓库有一些动作,这些动作包括
- Push events
- Tag push events
- Repository update events
- Merge request events
当发生以上任意一种事件时,就会以POST请求预定好的一个URL,并且带着本次事件的具体详情以JSON格式作为请求体。
以上这些功能很容易就能做到当仓库push,Tag push,或者Merge request push时就能自动触发,然后可以通过POST请求体可以在Web Server端轻松获取仓库的具体信息,从而实现打包
在克隆仓库之前预先读取一个配置文件
因为不是所有仓库都需要使用这项服务,一个判断的标准就是在项目的根目录下有没有Dockerfile
这个文件,那么问题就来了,如果每一个触发都要先clone代码下来之后在判断是否有Dockerfile这个文件理论上是没问题的。但实际上这样做可能会增加Gitlab的压力,当Gitlab的可用资源小于请求量时会被服务器拒绝服务,导致Docker自动打包服务质量下降。
解决这个问题的根结在于怎样才能直到当前触发的这个仓库根目录下是否有Dockerfile这个文件呢?
最好的方式就是通过HTTP的方式请求,首先你要创建一个Token,假定你要获取的文件名叫Dockerfile
,仓库ID是117
,那么以下的链接地址就可以直接获取文件内容
https://example.com/api/v4/projects/117/repository/files/Dockerfile/raw?ref=master&private_token=[Your token]
于是,我们可以用CURL轻松获取文件内容
$ curl https://example.com/api/v4/projects/117/repository/files/Dockerfile/raw?ref=master&private_token=[Your token]
FROM nginx
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY timeout.conf /etc/nginx/conf.d/timeout.conf
COPY build /usr/share/nginx/html/
当然,我们的目的不是为了获取文件内容,而是为了判断文件存不存在,所以我们只需要获取Response Headers就可以,这样避免Response Body一块传回而浪费网络传输字节的消耗
$ curl -Is https://example.com/api/v4/projects/117/repository/files/Dockerfile/raw?ref=master&private_token=[Your token] | head -n 1 | awk '{print $2}'
200
如果请求一个不存在的文件,会返回404状态码
$ curl -Is https://example.com/api/v4/projects/117/repository/files/not-exist-file/raw?ref=master&private_token=[Your token] | head -n 1 | awk '{print $2}'
404
如果文件名有特殊字符,需要提前URL编码以下,比如请求package.json
,编码之后应该是package%2Ejson
$ curl -Is https://example.com/api/v4/projects/117/repository/files/package%2Ejson/raw?ref=master&private_token=[Your token] | head -n 1 | awk '{print $2}'
200