极狐GitLab 镜像仓库
众所周知,极狐GitLab 是一个成熟、安全的一体化 DevOps 平台,其自身内置了容器镜像仓库功能,也即极狐GitLab Container Registry,用户可以将自身需要的镜像推送至极狐GitLab 镜像仓库,而无需自建镜像仓库或者使用已经采取了各种限制措施的 dockerhub。
极狐GitLab 的镜像仓库服务有三个不同级别:实例(Instance)级别、项目级别(Project)以及群组(Group)级别。实例级别需要管理员权限,而项目和群组级别则可以不需要管理员权限即可使用。下面分别介绍极狐GitLab 镜像仓库的使用和 API 等内容。
极狐GitLab 镜像仓库的使用
首先来看项目(Project)级别的镜像仓库使用。
项目级别的镜像仓库使用
可以通过每个项目的 Packages & Registries --> Container Registry来找到针对每个项目的镜像仓库的使用。如下图:
首先需要登录极狐GitLab 镜像仓库,使用如下命令:
$ docker login registry.gitlab.cn
在出现的对话框中输入用户名和密码即可登录成功。
密码可以是极狐GitLab 用户的登录密码,也可以是极狐GitLab 的 Personal Access Token。
可以写一个简单的 Dockerfile 来构建镜像并做镜像推送和使用测试:
FROM golang:1.12.9-alpine3.9 as builder
WORKDIR /tmp
COPY main.go /tmp
RUN go build main.go
FROM alpine:latest
WORKDIR /usr/src/app/
COPY --from=builder /tmp/devops /usr/src/app/
CMD ["./main"]
其中 main.go 的内容就是输出一个 Hello, 极狐GitLab,我是小马哥!!!。
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello,极狐GitLab,我是小马哥!!!"))
}
func main() {
http.HandleFunc("/jihu", handler)
log.Fatal(http.ListenAndServe(":9999", nil))
}
将上述两个文件放在一个新建的空文件目录下,执行如下命令即可开始镜像构建:
$ docker build -t registry.gitlab.cn/majinghe/devops:0.0.1 .
上述几个参数的含义:
- registry.gitlab.cn:极狐GitLab 镜像仓库的地址
- majinghe:极狐GitLab 的当前用户
- devops:项目名称
- 0.0.1: 镜像tag
需要注意的是,镜像名称的路径层级最多能达到三层, 也就是从项目名称开始,后面最多只能是两层。下面几种是有效的镜像名称写法:
registry.gitlab.cn/majinghe/devops:0.0.1
registry.gitlab.cn/majinghe/devops/my:0.0.1
registry.gitlab.cn/majinghe/devops/my/image:0.0.1
而
registry.gitlab.cn/majinghe/devops/my/image/test:0.0.1
是无效的,因为 devops/my/image/test 是四层,超过了三层,推送的时候会提示denied: requested access to the resource is denied:
$ docker push registry.gitlab.cn/majinghe/devops/my/image/test:0.0.1
The push refers to repository [registry.gitlab.cn/majinghe/devops/my/image/test]
27ce44cf221c: Preparing
9cb8bafb4446: Preparing
e2eb06d8af82: Preparing
denied: requested access to the resource is denied
填写正确的镜像名称,则可以看到如下构建输出:
[+] Building 2.5s (13/13) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 235B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 1.2s
=> [internal] load metadata for docker.io/library/golang:1.12.9-alpine3.9 2.3s
=> [builder 1/4] FROM docker.io/library/golang:1.12.9-alpine3.9@sha256:f6ea65be78b15375bf709cda1f32a4182d0b6a9f26d3dbd76685f5a32966e868 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 29B 0.0s
=> [stage-1 1/3] FROM docker.io/library/alpine:latest@sha256:e1c082e3d3c45cccac829840a25941e679c25d438cc8412c2fa221cf1a824e6a 0.0s
=> CACHED [stage-1 2/3] WORKDIR /usr/src/app/ 0.0s
=> CACHED [builder 2/4] WORKDIR /tmp 0.0s
=> CACHED [builder 3/4] COPY main.go /tmp 0.0s
=> CACHED [builder 4/4] RUN go build main.go 0.0s
=> [stage-1 3/3] COPY --from=builder /tmp/main /usr/src/app/ 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:25e31514018235303abbd36f36c39b45ac4896889ab9bc7f4e66b9a3d9f1e27a 0.0s
=> => naming to registry.gitlab.cn/majinghe/devops:0.0.1
随后即可将上述镜像推送至 devops 这个项目所对应的项目级别的镜像仓库:
$ docker push registry.gitlab.cn/majinghe/devops:0.0.1
The push refers to repository [registry.gitlab.cn/majinghe/devops]
27ce44cf221c: Pushed
9cb8bafb4446: Pushed
e2eb06d8af82: Pushed
0.0.1: digest: sha256:a15f3f2cd7b283a53eee53bb74a726b74f28b1488f0a3bc37b80d408fc54e4e1 size: 946
可以在其他服务器上用如下命令拉取存储在极狐GitLab 镜像仓库中的上述镜像来做测试:
$ docker run --rm -d -p 9999:9999 registry.gitlab.cn/majinghe/devops:0.0.1
fd4a8aed1938b5ab27265bf7023b9420614dd7ec4ef38e70bad55450cf828c42
然后在浏览器中输入localhost:9999/jihu 或者使用 curl 命令,可查看输出结果:
$ curl localhost:9999/jihu
Hello,极狐GitLab,我是小马哥!!!
可以看到存储在极狐GitLab devops项目所对应的镜像仓库中的镜像是可以被使用的。
群组级别的镜像仓库使用
群组级别的镜像仓库使用和项目级别的镜像仓库使用时类似的,可以在 Group --> Packages & Registries --> Container Registry 找到群组级别的镜像仓库服务。登录方式和项目级别的是一致的,即
$ docker login registry.gitlab.cn
重点在于构建镜像时的镜像名称有所不同,针对群租级别的镜像仓库,其镜像构建时的镜像名称格式如下:
$ registry.gitlab.cn/group-name/project-name:tag
比如,有一个名为 xiaomage 的群组,下面有一个 cr-demo 的项目,则构建命令为:
$ docker build -t registry.gitlab.cn/xiaomage/cr-demo:0.0.1 .
然后,推送至镜像仓库
$ docker push registry.gitlab.cn/xiaomage/cr-demo:0.0.1
针对于不同项目,只需要替换项目名称和 tag 即可完成镜像构建和推送。最后,可以在群组的镜像仓库中看到推送上来的镜像:
可以看到有两个镜像 cr-demo 和 var-demo,分别对应项目 cr-demo 和 var-demo。
一个有趣的测试:前面两个项目都存在于 xiaomage 这个群组下面的,如果要推送镜像至群组中不存在的项目下会怎么样呢?
$ docker build -t registry.gitlab.cn/xiaomage/cr1-demo:0.0.1 .
$ docker push registry.gitlab.cn/xiaomage/cr1-demo:0.0.1
The push refers to repository [registry.gitlab.cn/xiaomage/cr1-demo]
27ce44cf221c: Preparing
9cb8bafb4446: Preparing
e2eb06d8af82: Preparing
denied: requested access to the resource is denied
其中 cr1-demo 这个项目在群组 xiaomage 下面是不存在的,构建可以成功,但是推送的时候提示 denied: requested access to the resource is denied。 说明如果在群组中不存在某个项目,则用某个项目名称构建的镜像是无法推送至极狐GitLab 群组级别的镜像仓库中的。
和极狐GitLab CI 的集成使用
可以在极狐GitLab CI 中来使用极狐GitLab 镜像仓库,完成镜像的构建、推送以及使用。整个过程是用到了极狐GitLab 镜像仓库的一些预定义环境变量。关于极狐GitLab 预定义和自定义的环境变量,可以查看过往公众号文章极狐GitLab CI/CD 变量黑魔法你知道多少?(上)和极狐GitLab CI/CD 变量黑魔法你知道多少?(下)。
在 .gitlab-ci.yml 文件中写入如下内容
build:
stage: build
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
即可完成镜像仓库的登陆、镜像构建和推送。控制台中可以看到镜像仓库登陆和构建日志(构建日志太长,截取部分):
镜像推送的日志如下:
极狐GitLab 镜像仓库 API
极狐GitLab 提供了丰富的镜像仓库 API 来对镜像仓库执行相关操作。这样可以很方便的在其他 CI/CD 中系统中集成极狐GitLab 镜像仓库。
list 项目内的镜像仓库
$ curl --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token"\
"https://gitlab.cn/api/v4/projects/9106/registry/repositories?tags=1&tags_count=1
将获取的 token 替换之后,执行命令,返回结果为:
[
{
"id":157,
"name":"",
"path":"majinghe/devops",
"project_id":9106,
"location":"registry.gitlab.cn/majinghe/devops",
"created_at":"2021-10-08T16:28:25.319+08:00",
"cleanup_policy_started_at":null,
"tags_count":1,
"tags":[
{
"name":"0.0.1",
"path":"majinghe/devops:0.0.1",
"location":"registry.gitlab.cn/majinghe/devops:0.0.1"
}
]
}
]
可以看到镜像仓库内详细内容:有一个镜像仓库,id 是 157,下面有一个镜像,即registry.gitlab.cn/majinghe/devops:0.0.1。
delete 项目内的镜像仓库
$ curl --request DELETE --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token" \
> "https://gitlab.cn/api/v4/projects/project-id/registry/repositories/repositories-id"
- project-id:project 的 id,可以直接从极狐GitLab 项目页面获取到。
- repositories-id:repository 的 id,以 list API 为例,从输出结果看,为 157
成功的话返回结果为 202,随后,再用 list API 进行测试:
$ curl --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token" \
"https://gitlab.cn/api/v4/projects/9106/registry/repositories?tags=1&tags_count=true&name=true"
[]
可以看到,返回结果为空。
list 群组下面的镜像仓库
$ curl --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token" \
"https://gitlab.cn/api/v4/groups/group-id/registry/repositories?tags=1&tags_count=true"
- group-id:Group ID,可以直接在极狐GitLab Group 页面获取到。
返回结果如下:
[
{
"id":158,
"name":"",
"path":"xiaomage/var-demo",
"project_id":9693,
"location":"registry.gitlab.cn/xiaomage/var-demo",
"created_at":"2021-10-08T16:35:45.257+08:00",
"cleanup_policy_started_at":null,
"tags_count":1,
"tags":[
{
"name":"0.0.1",
"path":"xiaomage/var-demo:0.0.1",
"location":"registry.gitlab.cn/xiaomage/var-demo:0.0.1"
}
]
},
{
"id":159,
"name":"",
"path":"xiaomage/cr-demo",
"project_id":9786,
"location":"registry.gitlab.cn/xiaomage/cr-demo",
"created_at":"2021-10-08T16:42:58.681+08:00",
"cleanup_policy_started_at":null,
"tags_count":1,
"tags":[
{"name":"0.0.1",
"path":"xiaomage/cr-demo:0.0.1",
"location":"registry.gitlab.cn/xiaomage/cr-demo:0.0.1"
}
]
},
{
"id":160,
"name":"my/demo-image",
"path":"xiaomage/cr-demo/my/demo-image",
"project_id":9786,
"location":"registry.gitlab.cn/xiaomage/cr-demo/my/demo-image",
"created_at":"2021-10-08T16:59:06.896+08:00",
"cleanup_policy_started_at":null,
"tags_count":1,
"tags":[
{
"name":"0.0.1",
"path":"xiaomage/cr-demo/my/demo-image:0.0.1",
"location":"registry.gitlab.cn/xiaomage/cr-demo/my/demo-image:0.0.1"
}
]
可以看到群组 xiaomage 下面有三个 repository,id 分别为:158、159、160。每个 repository 都有 1 个镜像。
delete 群组下面的镜像仓库
由于群组下面的镜像仓库其实最终映射到了群组下面的项目中,所以删除群组下面的镜像仓库和删除某个项目下面的镜像仓库的 API 是一样的:
$ curl --request DELETE --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token" \
> "https://gitlab.cn/api/v4/projects/project-id/registry/repositories/repositories-id"
- project-id:project 的 id,可以直接从极狐GitLab 页面直接看到。
- repositories-id:repository 的 id,以list API 为例,从输出结果看,为 157。
成功的话返回结果为 202。
获取某个镜像的详细内容
$ curl --header "PRIVATE-TOKEN: MY-极狐GitLab-Personal-Token" \
> "https://gitlab.cn/api/v4/projects/project-id/registry/repositories/repository-id/tags/tag"
- project-id:project id,可以直接在极狐GitLab project 页面获取到。
- repository-id:repository id,可以从 list repository API 的返回值中得到。
- tag:镜像的 tag,诸如 0.0.1。
返回结果如下:
{
"name":"0.0.1",
"path":"xiaomage/var-demo:0.0.1",
"location":"registry.gitlab.cn/xiaomage/var-demo:0.0.1",
"revision":"25e31514018235303abbd36f36c39b45ac4896889ab9bc7f4e66b9a3d9f1e27a",
"short_revision":"25e315140",
"digest":"sha256:a15f3f2cd7b283a53eee53bb74a726b74f28b1488f0a3bc37b80d408fc54e4e1",
"created_at":"2021-10-08T08:21:55.701+00:00","total_size":6591030
}
删除指定 tag 的镜像
$ curl --request DELETE --header "PRIVATE-TOKEN: AdrW3vvLyWNyxnKUcwwv" \
> "https://gitlab.cn/api/v4/projects/9693/registry/repositories/158/tags/0.0.1"
成功的话,返回值为200。
可以用 list API 查看一下镜像:
$ curl --header "PRIVATE-TOKEN: AdrW3vvLyWNyxnKUcwwv" \
> "https://gitlab.cn/api/v4/projects/9693/registry/repositories/158/tags/0.0.1"
返回结果如下:
{"message":"404 Tag Not Found"}
也可以在镜像仓库的界面上看到,镜像已经被删除了。
当然,极狐GitLab 镜像仓库还有很多其他的 API,感兴趣的小伙伴可以查看 API 官方文档。
总结
极狐GitLab 镜像仓库使用方便,API 丰富,能够为用户提供灵活的镜像仓库解决方案。当然,镜像存储不仅仅是极狐GitLab 镜像仓库的功能,还有镜像扫描功能,将在后续为大家陆续揭秘。