diff --git a/.gitea/workflows/build-deploy.yml b/.gitea/workflows/build-deploy.yml new file mode 100644 index 0000000..a74586a --- /dev/null +++ b/.gitea/workflows/build-deploy.yml @@ -0,0 +1,84 @@ +name: Build and Deploy + +on: + push: + branches: + - main + +env: + REGISTRY: gitea.fse-media.group + IMAGE_NAME: henry_du/bywcloudreve + SERVER_HOST: 192.140.163.199 + SERVER_USER: ubuntu + COMPOSE_PATH: /home/ubuntu/cloudreve + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Gitea Container Registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ gitea.actor }} + password: ${{ secrets.GITEA_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=sha,format=long,prefix= + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./Dockerfile.ci + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64 + cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + cache-to: type=inline + build-args: | + BUILD_DATE=${{ gitea.sha }} + + - name: Deploy to server via SSH + uses: appleboy/ssh-action@v1.2.0 + with: + host: ${{ env.SERVER_HOST }} + username: ${{ env.SERVER_USER }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + port: 22 + script: | + set -e + cd ${{ env.COMPOSE_PATH }} + + echo "${{ secrets.GITEA_TOKEN }}" | docker login ${{ env.REGISTRY }} -u "${{ gitea.actor }}" --password-stdin + + echo "Pulling latest image..." + docker compose pull cloudreve + + echo "Recreating cloudreve container (preserving volumes)..." + docker compose up -d --remove-orphans cloudreve + + echo "Cleaning up old images..." + docker image prune -f + + echo "Deployment completed at $(date)" diff --git a/Dockerfile.ci b/Dockerfile.ci new file mode 100644 index 0000000..5df2dc8 --- /dev/null +++ b/Dockerfile.ci @@ -0,0 +1,91 @@ +# syntax=docker/dockerfile:1.6 + +ARG FRONTEND_MIRROR=https://gitclone.com/github.com/cloudreve/frontend.git +ARG GO_PROXY=https://goproxy.cn,direct +ARG NPM_REGISTRY=https://registry.npmmirror.com + +# ======================================== +# Stage 1: Frontend build +# ======================================== +FROM node:20-alpine AS frontend-build +ARG FRONTEND_MIRROR +ARG NPM_REGISTRY + +WORKDIR /build +RUN apk add --no-cache git zip tzdata + +RUN --mount=type=cache,target=/tmp/git-cache \ + git clone --depth 1 ${FRONTEND_MIRROR} assets + +WORKDIR /build/assets +RUN npm config set registry ${NPM_REGISTRY} && \ + yarn config set registry ${NPM_REGISTRY} + +RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \ + --mount=type=cache,target=/build/assets/node_modules \ + yarn install --network-timeout 1000000 --frozen-lockfile || yarn install --network-timeout 1000000 + +RUN export NODE_OPTIONS="--max-old-space-size=8192" && yarn run build + +WORKDIR /build +RUN mkdir -p application/statics && \ + cd assets/build && zip -r - . > /build/application/statics/assets.zip + +# ======================================== +# Stage 2: Backend build +# ======================================== +FROM golang:1.23-alpine AS backend-build +ARG GO_PROXY + +WORKDIR /src +RUN apk add --no-cache git tzdata gcc musl-dev + +ENV CGO_ENABLED=0 \ + GOOS=linux \ + GOARCH=amd64 \ + GOPROXY=${GO_PROXY} + +COPY go.mod go.sum ./ +RUN --mount=type=cache,target=/go/pkg/mod \ + go mod download + +COPY . . +COPY --from=frontend-build /build/application/statics/assets.zip ./application/statics/assets.zip + +RUN --mount=type=cache,target=/go/pkg/mod \ + --mount=type=cache,target=/root/.cache/go-build \ + go build -trimpath -ldflags "-s -w -X 'github.com/cloudreve/Cloudreve/v4/pkg/conf.BackendVersion=byw-${BUILD_DATE:-dev}'" -o /cloudreve . + +# ======================================== +# Stage 3: Runtime image +# ======================================== +FROM alpine:latest AS runtime + +WORKDIR /cloudreve + +RUN apk update && \ + apk add --no-cache tzdata vips-tools ffmpeg libreoffice aria2 supervisor font-noto font-noto-cjk libheif libraw-tools && \ + cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ + echo "Asia/Shanghai" > /etc/timezone && \ + mkdir -p ./data/temp/aria2 && \ + chmod -R 766 ./data/temp/aria2 && \ + rm -rf /var/cache/apk/* + +ENV CR_ENABLE_ARIA2=1 \ + CR_SETTING_DEFAULT_thumb_ffmpeg_enabled=1 \ + CR_SETTING_DEFAULT_thumb_vips_enabled=1 \ + CR_SETTING_DEFAULT_thumb_libreoffice_enabled=1 \ + CR_SETTING_DEFAULT_media_meta_ffprobe=1 \ + CR_SETTING_DEFAULT_thumb_libraw_enabled=1 + +COPY .build/aria2.supervisor.conf .build/entrypoint.sh ./ +COPY --from=backend-build /cloudreve ./cloudreve + +RUN chmod +x ./cloudreve && \ + chmod +x ./entrypoint.sh + +EXPOSE 5212 443 6888 6888/udp + +VOLUME ["/cloudreve/data"] + +ENTRYPOINT ["sh", "./entrypoint.sh"] diff --git a/docker-compose.server.yml b/docker-compose.server.yml new file mode 100644 index 0000000..736f552 --- /dev/null +++ b/docker-compose.server.yml @@ -0,0 +1,47 @@ +services: + cloudreve: + image: gitea.fse-media.group/henry_du/bywcloudreve:latest + container_name: cloudreve-backend + depends_on: + - postgresql + - redis + restart: unless-stopped + ports: + - 5212:5212 + - 6888:6888 + - 6888:6888/udp + environment: + - CR_CONF_Database.Type=postgres + - CR_CONF_Database.Host=postgresql + - CR_CONF_Database.User=cloudreve + - CR_CONF_Database.Name=cloudreve + - CR_CONF_Database.Port=5432 + - CR_CONF_Redis.Server=redis:6379 + volumes: + - backend_data:/cloudreve/data + + postgresql: + image: postgres:17 + container_name: postgresql + restart: unless-stopped + environment: + - POSTGRES_USER=cloudreve + - POSTGRES_DB=cloudreve + - POSTGRES_HOST_AUTH_METHOD=trust + volumes: + - database_postgres:/var/lib/postgresql/data + + redis: + image: redis:latest + container_name: redis + restart: unless-stopped + volumes: + - redis_data:/data + +volumes: + backend_data: + external: false + database_postgres: + external: false + redis_data: + external: false