Docker构建自定义镜像

在Gitlab Pipeline中集成进ut覆盖率和测试报告中提到存在可改进之处,即单次CI耗时过长。


耗时主要在下载diff_cover(需要下载pip),以及Golang(用的是docker image)以及gocover-cobertura和gotestsum

考虑将这些工具打包在一起,构建成一个新的镜像,CI阶段就可以大幅度降低耗时


Dockerfile如下:

1
2
3
4
FROM  golang:latest

RUN echo '这是一个爽哥构建的一个工具'
RUN apt-get update && apt install python3-pip -y && pip3 install diff_cover && go env -w GOPROXY="https://goproxy.cn,direct" && go get github.com/boumenot/gocover-cobertura@v1.2.0 && go get gotest.tools/gotestsum@v1.7.0

因为Docker是分层下载,每一个RUN就是单独一层。所以尽可能如上这样写,而不要写多个RUN

执行docker build -t ci_tool:v1 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[+] Building 547.2s (4/7)                                                                                                                                              
[+] Building 547.6s (4/7)
[+] Building 548.0s (4/7)
[+] Building 635.7s (7/8)
[+] Building 635.9s (7/8)
[+] Building 636.0s (7/8)
[+] Building 636.2s (7/8)
[+] Building 636.3s (7/8)
[+] Building 685.9s (7/8)
=> => extracting sha256:94a23d3cb5be24659b25f17537307e7f568d665244f6a383c1c6e51e31080749 1.5s
=> => sha256:499ac46314c257f999ffe452e3a4ac1c8bc46c373f461074d4737870caca50bd 102.65MB / 102.65MB 144.3s
[+] Building 687.3s (7/8)
[+] Building 694.8s (9/9) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 342B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/golang:latest 5.4s
=> [auth] library/golang:pull token for registry-1.docker.io 0.0s
=> [1/3] FROM docker.io/library/golang:latest@sha256:0fa6504d3f1613f554c42131b8bf2dd1b2346fb69c2fc24a312e7cba6c87a71e 627.8s
=> => resolve docker.io/library/golang:latest@sha256:0fa6504d3f1613f554c42131b8bf2dd1b2346fb69c2fc24a312e7cba6c87a71e 0.0s
=> => sha256:ac9d381bd1e98fa8759f80ff42db63c8fce4ac9407b2e7c8e0f031ed9f96432b 5.14MB / 5.14MB 11.6s
=> => sha256:aa9c5b49b9db3dd2553e8ae6c2081b77274ec0a8b1f9903b0e5ac83900642098 10.66MB / 10.66MB 26.6s
=> => sha256:0fa6504d3f1613f554c42131b8bf2dd1b2346fb69c2fc24a312e7cba6c87a71e 2.35kB / 2.35kB 0.0s 0.4s
=> => sha256:89b5d1fa04af24c4cae53f775b9382755b2ba1082bda77b9f8febaa8676b54cb 1.80kB / 1.80kB 0.0s
=> => sha256:cac175c1423a6f67bcf70033345b7dc7d733176ab28932904a3e457acc6f5c56 7.08kB / 7.08kB 0.0s
=> => sha256:94a23d3cb5be24659b25f17537307e7f568d665244f6a383c1c6e51e31080749 53.60MB / 53.60MB 84.6s
=> => sha256:841dd868500b6685b6cda93c97ea76e817b427d7a10bf73e9d03356fac199ffd 54.67MB / 54.67MB 618.3s 0.4s
=> => sha256:627b3401fb617535edd16e96bd5941ecea7fe10ce6087bd47707602cfc396c2b 81.01MB / 81.01MB 157.3s
=> => extracting sha256:94a23d3cb5be24659b25f17537307e7f568d665244f6a383c1c6e51e31080749 1.5s
=> => sha256:499ac46314c257f999ffe452e3a4ac1c8bc46c373f461074d4737870caca50bd 102.65MB / 102.65MB 144.3s
=> => extracting sha256:ac9d381bd1e98fa8759f80ff42db63c8fce4ac9407b2e7c8e0f031ed9f96432b 0.1s
=> => extracting sha256:aa9c5b49b9db3dd2553e8ae6c2081b77274ec0a8b1f9903b0e5ac83900642098 0.2s
=> => sha256:63c2674d92dba6ae349f7ae5d7460b37a9dc8744644dedd1f83d0ed1dbd7c806 124B / 124B 145.7s
=> => extracting sha256:841dd868500b6685b6cda93c97ea76e817b427d7a10bf73e9d03356fac199ffd 1.7s
=> => extracting sha256:627b3401fb617535edd16e96bd5941ecea7fe10ce6087bd47707602cfc396c2b 2.2s
=> => extracting sha256:499ac46314c257f999ffe452e3a4ac1c8bc46c373f461074d4737870caca50bd 3.0s
=> => extracting sha256:63c2674d92dba6ae349f7ae5d7460b37a9dc8744644dedd1f83d0ed1dbd7c806 0.0s
=> [auth] library/golang:pull token for registry-1.docker.io 0.0s
=> [2/3] RUN echo '这是一个爽哥构建的一个工具' 0.4s
=> [3/3] RUN apt-get update && apt install python3-pip -y && pip3 install diff_cover && go env -w GOPROXY="https://goproxy.cn,direct" && go get github.com/boumenot/gocover-cobertura@v1.2.0 && go get gotest.tools/gotestsum@ 59.3s
=> exporting to image 1.6s
=> => exporting layers 1.6s
=> => writing image sha256:28a8ad1ca810ef0c17b80390c809d7fe3fc327e6dc8c4a8a994df1d9b69d057f 0.0s
=> => naming to docker.io/library/ci_tool:v1 0.0s

Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them

启动,而后执行docker exec -it 容器id /bin/sh 进入容器,

可见符合预期~


将其push到dockerhub时报错,denied: requested access to the resource is denied

这是因为构建时要在前面加上自己的dockerhub的username


执行docker build -t cuishuang/ci_tool:v1 . 重新构建并push

之后在hub.docker.com/就能够看到


发现上面的Dockerfile漏了go get github.com/axw/gocov/…go get github.com/AlekSi/gocov-xml这两步,在Dockerfile加上,

1
2
3
4
FROM  golang:latest

RUN echo '这是一个爽哥构建的一个工具'
RUN apt-get update && apt install python3-pip -y && pip3 install diff_cover && go env -w GOPROXY="https://goproxy.cn,direct" && go get github.com/boumenot/gocover-cobertura@v1.2.0 && go get gotest.tools/gotestsum@v1.7.0 && go get github.com/axw/gocov/... && go get github.com/AlekSi/gocov-xml

docker build -t cuishuang/ci_tool:v2 . 重新构建,而后push到dockerhub


而后便可改造之前项目.gitlab-ci.yml

并进行提交


发现Pipeline-Unittest阶段失败

具体原因为:

failed to pull image "cuishuang/ci_tool:latest" with specified policies [always]: Error response from daemon: manifest for cuishuang/ci_tool:latest not found: manifest unknown: manifest unknown (manager.go:203:19s)


image: cuishuang/ci_tool:latest改为image: cuishuang/ci_tool:v2并提交。

发现可以pull到该镜像,但执行一些命令时失败:


在实际跑gitlab-runner的ubuntu机器上(amd架构),启动上面构建的镜像:

docker run --name shuang_tool -d cuishuang/ci_tool:v2

而后进入,发现镜像启动失败


在本机(Mac M1,arm架构)启动,却没有该问题。

参考这篇,应该是arm和amd架构导致的问题


在ubuntu机器上新建Dockerfile, docker build -t cuishuang/ci_tool:v3 .进行构建

而后push到dockerhub。


但在ubuntu上apt-get update命令总失败

尝试看下docker能不能像go build一样可以交叉编译

跨平台构建 Docker 镜像新姿势,x86、arm 一把梭

继续解决apt-get update命令失败的问题,换一下源就可以了

docker ubuntu 换源

如果更换后出现类似The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 3B4FE6ACC0B21F32 这样的错误,可通过sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys xxxxxx 解决

一番尝试后,发现apt-get update及之后pip3 install diff_cover有各种各样的坑…。

(可以将相关的去掉然后构建,进入容器中去执行,发现报的这些依赖问题依然不好解决)

为绕过这些坑,聚焦主线,将之前的使用到diff-cover工具的部分去掉

(另外为了方便找到失败的原因,可将之前写在一个RUN里的多条命令拆开,一个命令一个RUN,这样容易获悉是哪一条命令执行出错)


同时将在ubuntu上构建出的镜像上传到docker hub


将改动提交,而后进入pipeline流程,可以看到shuang-unit-test阶段的job执行成功




这样就把CI的shuang-unit-test阶段用到的各种工具放在了一起,只需要拉取这个镜像即可~

(pull这个镜像比那各种现场apt update,go get要快太多了…)

docker镜像采用分层机制,在默认的官方golang镜像基础上,添加新的工具~

而官方的golang镜像默认是基于ubuntu系统,体积较大,拉取时间较长


构建后的镜像达到了1.05GB,压缩后也近400MB

一般都用基于精简款linux的alpine的来构建,可参考这篇

基于alpine构建体积更小的Docker镜

文章目录