因为默认版本的 Drone 包含构建次数限制,如果日常高频使用 Drone,不久之后,便会遇到需要“重新初始化”应用才能继续使用的问题,但其实,作为个人用户,我们其实可以不受此限制影响。
所以本篇文章,就来分享下如何使用容器方式构建无使用限制的 Drone CI。
之所以会有这篇文章出现呢?因为之前折腾群里的同学“公子”曾提到过“Drone 默认镜像是企业版,有 5000 次构建限制,需要重新编译”。考虑到软件的长期稳定使用,对官方文档进行翻阅,看到情况确实如此,文档中是如此描述的:“存在两种版本的 Drone,分别是需要自行构建的社区开源版本,和官方提供的企业版本”,然而官方并没有更多对于编译构建相关的文档或者说明。
对于个人开发者或者团队来说,我们最关心的几个问题,莫过于代码是否安全、软件授权方式、以及授权费用了,官方文档中有提及:
在官方企业服务页面,我们可以看到不同版本的功能区别,主要在于是否支持:分布式方式运行多个 Runner;使用 K8S Runner;支持组织密钥功能;支持搭配 Vault 使用;支持定时任务;支持使用 postgres、mysql、s3 进行数据存储;支持自动扩容以及“扩展功能”。
如果你有上述需求,可以构建“企业版”、反之构建“开源版”即可。不过结合上面的使用限制,对于一般个人和团队来说,直接构建“企业版”会更省事一些,功能更加全面。
那么,就来看看如何采取类似“官方的方式”编译构建 Drone 的容器镜像吧。
翻阅文档,可以看到关于自行构建,只有两条(或者说一条)简单的命令:
# 构建开源版
$ go build -tags "oss nolimit" github.com/drone/drone/cmd/drone-server
# 构建企业版
$ go build -tags "nolimit" github.com/drone/drone/cmd/drone-server
为了构建出和官方基本一致的镜像,需要从官方仓库中梳理完整的“构建套路”。这里以 v1.10.1 代码为基础,进行构建方式梳理。
从仓库根目录的 BUILDING
和 BUILDING_OSS
文件,可以看到记录了两种发行版软件的安装和构建流程:
1. Clone the repository
2. Install go 1.11 or later with Go modules enabled
3. Install binaries to $GOPATH/bin
go install -tags "oss nolimit" github.com/drone/drone/cmd/drone-server
4. Start the server at localhost:8080
export DRONE_GITHUB_CLIENT_ID=...
export DRONE_GITHUB_CLIENT_SECRET=...
drone-server
继续翻阅项目的 .drone.yml
CI 文件,可以看到官方是如何通过 CI 构建和发布软件的:
...
- name: build
image: golang:1.14.4
commands:
- sh scripts/build.sh
environment:
GOARCH: amd64
GOOS: linux
- name: publish
image: plugins/docker:18
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
dockerfile: docker/Dockerfile.server.linux.amd64
repo: drone/drone
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
- push
- tag
...
按图索骥,翻阅 CI 文件中提到的“构建脚本”,内容如下:
#!/bin/sh
echo "building docker images for ${GOOS}/${GOARCH} ..."
REPO="github.com/drone/drone"
# compile the server using the cgo
go build -ldflags "-extldflags \"-static\"" -o release/linux/${GOARCH}/drone-server ${REPO}/cmd/drone-server
# compile the runners with gcc disabled
export CGO_ENABLED=0
go build -o release/linux/${GOARCH}/drone-agent ${REPO}/cmd/drone-agent
go build -o release/linux/${GOARCH}/drone-controller ${REPO}/cmd/drone-controller
继续查看容器 Dockerfile docker/Dockerfile.server.linux.amd64 ,可以看到容器结构:
# docker build --rm -f docker/Dockerfile -t drone/drone .
FROM alpine:3.11 as alpine
RUN apk add -U --no-cache ca-certificates
FROM alpine:3.11
EXPOSE 80 443
VOLUME /data
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
ENV GODEBUG netdns=go
ENV XDG_CACHE_HOME /data
ENV DRONE_DATABASE_DRIVER sqlite3
ENV DRONE_DATABASE_DATASOURCE /data/database.sqlite
ENV DRONE_RUNNER_OS=linux
ENV DRONE_RUNNER_ARCH=amd64
ENV DRONE_SERVER_PORT=:80
ENV DRONE_SERVER_HOST=localhost
ENV DRONE_DATADOG_ENABLED=true
ENV DRONE_DATADOG_ENDPOINT=https://stats.drone.ci/api/v1/series
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
ADD release/linux/amd64/drone-server /bin/
ENTRYPOINT ["/bin/drone-server"]
线索差不多齐了,我们开始编写基础的容器镜像。
上一小节中,我们可以看到容器文件中使用的核心的软件 drone-server
是从“本地”拷贝至镜像中的,猜测是为了更高的编译效率,使用更短时间编译多平台使用的二进制文件,所以采取了这样的策略。
对于我们来说,只需要使用适用于某一种 CPU 架构和系统的软件,可以考虑将编译环境直接用容器来创建。除了能够更好的保存编译环境外,还能够让编译使用的机器系统环境更加“纯粹和干净”:
FROM golang:1.16.0-alpine3.13 AS Builder
ENV DRONE_VERSION 1.10.1
ENV CGO_CFLAGS="-g -O2 -Wno-return-local-addr"
RUN apk add build-base && go env -w GO111MODULE=on && \
mkdir /src && cd /src && \
apk add curl && curl -L https://github.com/drone/drone/archive/refs/tags/v${DRONE_VERSION}.tar.gz -o v${DRONE_VERSION}.tar.gz && \
tar zxvf v${DRONE_VERSION}.tar.gz && rm v${DRONE_VERSION}.tar.gz && \
cd /src/drone-${DRONE_VERSION} && \
go mod download && \
go build -ldflags "-extldflags \"-static\"" -tags="nolimit" github.com/drone/drone/cmd/drone-server
为了让构建速度加快,我们可以适当调整 Dockerfile ,添加一些国内的软件源:
FROM golang:1.16.0-alpine3.13 AS Builder
RUN sed -i 's/https:\/\/dl-cdn.alpinelinux.org/http:\/\/mirrors.tuna.tsinghua.edu.cn/' /etc/apk/repositories && \
echo "Asia/Shanghai" > /etc/timezone
RUN apk add build-base && \
go env -w GO111MODULE=on && \
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
ENV DRONE_VERSION 1.10.1
WORKDIR /src
# Build with online code
RUN apk add curl && curl -L https://github.com/drone/drone/archive/refs/tags/v${DRONE_VERSION}.tar.gz -o v${DRONE_VERSION}.tar.gz && \
tar zxvf v${DRONE_VERSION}.tar.gz && rm v${DRONE_VERSION}.tar.gz
# OR with offline tarball
# ADD drone-1.10.1.tar.gz /src/
WORKDIR /src/drone-${DRONE_VERSION}
RUN go mod download
ENV CGO_CFLAGS="-g -O2 -Wno-return-local-addr"
RUN go build -ldflags "-extldflags \"-static\"" -tags="nolimit" github.com/drone/drone/cmd/drone-server
将上面的内容保存为 Dockerfile
,然后执行 docker build -t drone:1.10.1 .
,稍等片刻“全功能”的 Drone 就在镜像内构建完毕了,但是镜像尺寸非常大,足足有 1.28GB 之大,所以我们要继续编写一个多阶段构建的镜像,来减少容器尺寸。
在上面的容器声明文件下方继续添加一些内容,结合前文找到的官方构建脚本,我们可以对构建脚本进行一些调整:
FROM golang:1.16.0-alpine3.13 AS Builder
RUN sed -i 's/https:\/\/dl-cdn.alpinelinux.org/http:\/\/mirrors.tuna.tsinghua.edu.cn/' /etc/apk/repositories && \
echo "Asia/Shanghai" > /etc/timezone
RUN apk add build-base && \
go env -w GO111MODULE=on && \
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
ENV DRONE_VERSION 1.10.1
WORKDIR /src
# Build with online code
RUN apk add curl && curl -L https://github.com/drone/drone/archive/refs/tags/v${DRONE_VERSION}.tar.gz -o v${DRONE_VERSION}.tar.gz && \
tar zxvf v${DRONE_VERSION}.tar.gz && rm v${DRONE_VERSION}.tar.gz
# OR with offline tarball
# ADD drone-1.10.1.tar.gz /src/
WORKDIR /src/drone-${DRONE_VERSION}
RUN go mod download
ENV CGO_CFLAGS="-g -O2 -Wno-return-local-addr"
RUN go build -ldflags "-extldflags \"-static\"" -tags="nolimit" github.com/drone/drone/cmd/drone-server
FROM alpine:3.13 AS Certs
RUN sed -i 's/https:\/\/dl-cdn.alpinelinux.org/http:\/\/mirrors.tuna.tsinghua.edu.cn/' /etc/apk/repositories && \
echo "Asia/Shanghai" > /etc/timezone
RUN apk add -U --no-cache ca-certificates
FROM alpine:3.13
EXPOSE 80 443
VOLUME /data
RUN [ ! -e /etc/nsswitch.conf ] && echo 'hosts: files dns' > /etc/nsswitch.conf
ENV GODEBUG netdns=go
ENV XDG_CACHE_HOME /data
ENV DRONE_DATABASE_DRIVER sqlite3
ENV DRONE_DATABASE_DATASOURCE /data/database.sqlite
ENV DRONE_RUNNER_OS=linux
ENV DRONE_RUNNER_ARCH=amd64
ENV DRONE_SERVER_PORT=:80
ENV DRONE_SERVER_HOST=localhost
ENV DRONE_DATADOG_ENABLED=true
ENV DRONE_DATADOG_ENDPOINT=https://stats.drone.ci/api/v1/series
COPY --from=Certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=Builder /src/drone-1.10.1/drone-server /bin/drone-server
ENTRYPOINT ["/bin/drone-server"]
再次执行 docker build -t drone:1.10.1 .
,能够看到镜像尺寸减少到了 61.7MB
,和官方提供的 67.3MB 镜像差不多大了。
今年早些时候,曾写过一篇关于 Drone 的内容:《容器方式下的轻量仓库与CI 使用方案:Gitea + Drone 基础篇》,前些天在《站点优化日志(2021.04.12)》 中,也曾提到过我在尝试使用 Gitea + Drone 替换之前个人使用的 GitLab,所以如果你有类似轻量化运行的需求,可以翻阅之前的文章,或许能节约一些折腾过程的时间。
当然,如果你对 GitLab Runner 的编译构建感兴趣,可以翻阅两年前的一篇内容:《源码编译 GitLab Runner》,同样是使用 Golang 编写,但是相比之下,比 Drone 复杂不少。
希望这篇文章能够帮到使用 Drone 的你。
–EOF
我们有一个小小的折腾群,里面聚集了一些喜欢折腾的小伙伴。
在不发广告的情况下,我们在里面会一起聊聊软硬件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术沙龙的资料。
喜欢折腾的小伙伴欢迎扫码添加好友。(请注明来源和目的,备注实名,否则不会通过审核)
本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)
本文作者: 苏洋
创建时间: 2021年04月17日
统计字数: 7325字
阅读时间: 15分钟阅读
本文链接: https://soulteary.com/2021/04/17/use-docker-to-build-drone-ci-without-functional-limitations.html