免责声明
这个教程只是个人实践,不保证成功复现率,如果有什么问题可以在这里跟帖,我看到了会回复;
另外根据使用条款,捐助版构建的镜像请仅限于捐助者个人(或团队内部)使用,请不要公开或是分发!
特殊解决方案
有一种解决方案自然是手动下载发布的预构建文件之后封装到 docker 基础的容器镜像(比如 alpine )里面去,这种解决方案太过神奇所以暂时不多说,这里主要讲的是从源码构建的方案,以方便二开的用户(虽然感觉按照二开用户的技术能力大概未必需要阅读这篇水文233333)
两个注意事项
- 从专业版管理页面下载到的源程序已经是完整的了,前端在 assets 目录中,剩下部分则是后端的代码;
- 自带的 .gitmodules 和 Dockerfile 文件需要调整,前者引用了私有仓库需要改一下指向,后者版本有些老旧会构建失败。
调整文件
调整 .gitmodules
推荐按照官方这种前后端分仓库,然后使用 submodule 的方式将 assets 目录引用过来,这样一方面方便维护,另一方面也不容易导致仓库混乱。
需要注意的是不同 CI/CD 平台对 .gitmodules 的处理方式不尽相同,尤其是作为私有仓库的处理上,比如在 GitLab 上需要使用相对路径的方式,这样 CI 在拉取文件的时候不会出现权限问题。
比如我的 .gitmodules 文件长这样(前后端仓库同属一个组织下):
[submodule "assets"]
path = assets
url = ../cloudreve-pro-frontend.git
调整 Dockerfile
我选择的是参照开源版本的 Dockerfile 文件,但需要修改第 8 行拉取代码的来源和第 24 行注入 flags 的包名。
拉取代码的来源不能再使用 github 仓库了,要改成从宿主目录中复制文件进去。一个比较常用的写法是 COPY . .
,表示将宿主机当前工作目录的文件全部拷贝入容器中。
关于包名,其实我不确定开源版本的这个包名会不会带来问题,在写这个 post 的时候包名还是 github.com/HFO4/cloudreve ,在 CI 上会提示注入失败报错,所以我改成了 go.mod 文件中描述的 github.com/cloudreve/Cloudreve/v3 ,也就是保证包名拼接上后面的路径里面存在一个文件 (此处是 version.go ) 里有可以用来注入的变量 BackendVersion 和 LastCommit )。
其实 Dockerfile 严格来讲还可以再把前后端的构建容器拆分开,但我懒得再折腾了(摊手x
印象里就这两点,我的 Dockerfile 长这样:
FROM golang:1.18-alpine as cloudreve_builder
# install dependencies and build tools
RUN apk update && apk add --no-cache wget curl git yarn build-base gcc abuild binutils binutils-doc gcc-doc zip
WORKDIR /cloudreve_builder
COPY . .
# build frontend
WORKDIR /cloudreve_builder/assets
# Disable sourcemap in production envitonment
ENV GENERATE_SOURCEMAP false
# Disable new OpenSSL to prevent 0308010C:digital envelope routines::unsupported
ENV NODE_OPTIONS --openssl-legacy-provider
RUN yarn install --network-timeout 1000000
RUN yarn run build
# build backend
WORKDIR /cloudreve_builder
RUN zip -r - assets/build >assets.zip
RUN tag_name=$(git describe --tags) \
&& export COMMIT_SHA=$(git rev-parse --short HEAD) \
&& go build -a -o cloudreve -ldflags " -X 'github.com/cloudreve/Cloudreve/v3/pkg/conf.BackendVersion=$tag_name' -X 'github.com/cloudreve/Cloudreve/v3/pkg/conf.LastCommit=$COMMIT_SHA'"
# build final image
FROM alpine:latest
WORKDIR /cloudreve
RUN apk update && apk add --no-cache tzdata
# we using the `Asia/Shanghai` timezone by default, you can do modification at your will
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone
COPY --from=cloudreve_builder /cloudreve_builder/cloudreve ./
# prepare permissions and aria2 dir
RUN chmod +x ./cloudreve && mkdir -p /data/aria2 && chmod -R 766 /data/aria2
EXPOSE 5212
VOLUME ["/cloudreve/uploads", "/cloudreve/avatar", "/data"]
ENTRYPOINT ["./cloudreve"]
具体的 CI 配置文件
这里各个平台都不一样, GitHub 上的解决思路可以参考官方的 docker-release.yml ,GitLab 上的解决方案可以参考这个:
stages:
- build
build-job:
stage: build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
variables:
GIT_SUBMODULE_STRATEGY: recursive
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json
- >-
/kaniko/executor
--context "${CI_PROJECT_DIR}"
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
--destination "${CI_REGISTRY_IMAGE}:latest"
--destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHORT_SHA}"