diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e4dd5576..870f5ad4b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -511,3 +511,76 @@ jobs: body_path: release-notes.extracted.md prerelease: ${{ github.event.pull_request.draft }} generate_release_notes: false + + publish_images: + name: Publish ${{ matrix.image.name }} image + needs: publish_release + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + strategy: + fail-fast: false + matrix: + image: + - name: backend + context: backend + dockerfile: backend/Dockerfile + - name: frontend + context: frontend + dockerfile: frontend/Dockerfile + + steps: + - name: Checkout release source + uses: actions/checkout@v7 + with: + ref: ${{ needs.publish_release.outputs.tag }} + + - name: Check latest release + id: release + env: + GH_TOKEN: ${{ github.token }} + TARGET_TAG: ${{ needs.publish_release.outputs.tag }} + run: | + latest_tag="$(gh api "repos/${GITHUB_REPOSITORY}/releases/latest" --jq .tag_name)" + if [ "$TARGET_TAG" = "$latest_tag" ]; then + echo "is_latest=true" >> "$GITHUB_OUTPUT" + else + echo "is_latest=false" >> "$GITHUB_OUTPUT" + fi + + - name: Set up QEMU + uses: docker/setup-qemu-action@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Log in to GHCR + uses: docker/login-action@v4 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@v6 + with: + images: ghcr.io/dataelement/clawith-${{ matrix.image.name }} + tags: | + type=raw,value=${{ needs.publish_release.outputs.tag }} + type=raw,value=latest,enable=${{ steps.release.outputs.is_latest == 'true' }} + labels: | + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.version=${{ needs.publish_release.outputs.tag }} + org.opencontainers.image.revision=${{ github.sha }} + + - name: Build and push + uses: docker/build-push-action@v7 + with: + context: ${{ matrix.image.context }} + file: ${{ matrix.image.dockerfile }} + push: true + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/README.md b/README.md index f27d7a957..42f1b6d5c 100644 --- a/README.md +++ b/README.md @@ -121,14 +121,17 @@ bash restart.sh ```bash git clone https://github.com/dataelement/Clawith.git cd Clawith && cp .env.example .env +# Pull prebuilt images from GitHub Container Registry docker compose up -d # → http://localhost:3008 +# Build from the checked-out source instead +# docker compose up -d --build ``` **To update an existing deployment:** ```bash git pull -docker compose up -d --build +docker compose pull && docker compose up -d ``` **Agent workspace data storage:** diff --git a/README_ar.md b/README_ar.md index 4c38f0931..53d472065 100644 --- a/README_ar.md +++ b/README_ar.md @@ -160,14 +160,17 @@ bash restart.sh ```bash git clone https://github.com/dataelement/Clawith.git cd Clawith && cp .env.example .env +# سحب الصور المسبقة البناء من GitHub Container Registry docker compose up -d -# → http://localhost:3000 +# → http://localhost:3008 +# البناء من المصدر الحالي بدلاً من ذلك +# docker compose up -d --build ``` **لتحديث نشر موجود:** ```bash git pull -docker compose up -d --build +docker compose pull && docker compose up -d ``` **تخزين بيانات مساحة عمل الوكيل:** diff --git a/README_es.md b/README_es.md index 9bf826522..22d3a09de 100644 --- a/README_es.md +++ b/README_es.md @@ -92,6 +92,24 @@ bash restart.sh # Inicia los servicios > **Nota:** `setup.sh` detecta automáticamente PostgreSQL disponible. Si no encuentra ninguno, **descarga e inicia una instancia local automáticamente**. Para usar una instancia específica de PostgreSQL, configure `DATABASE_URL` en el archivo `.env`. +### Docker + +```bash +git clone https://github.com/dataelement/Clawith.git +cd Clawith && cp .env.example .env +# Descargar imágenes precompiladas desde GitHub Container Registry +docker compose up -d +# → http://localhost:3008 +# Compilar desde el código fuente actual +# docker compose up -d --build +``` + +**Para actualizar un despliegue existente:** +```bash +git pull +docker compose pull && docker compose up -d +``` + El primer usuario en registrarse se convierte automáticamente en **administrador de la plataforma**. ### Solución de Problemas de Red diff --git a/README_ja.md b/README_ja.md index e7eea03ed..1ab5c369a 100644 --- a/README_ja.md +++ b/README_ja.md @@ -92,6 +92,24 @@ bash restart.sh # サービス起動 > **注意:** `setup.sh` は利用可能な PostgreSQL を検出します。見つからない場合は**自動的にローカルインスタンスをダウンロードして起動します**。特定の PostgreSQL インスタンスを使用する場合は、`.env` ファイルで `DATABASE_URL` を設定してください。 +### Docker + +```bash +git clone https://github.com/dataelement/Clawith.git +cd Clawith && cp .env.example .env +# GitHub Container Registry からビルド済みイメージを取得 +docker compose up -d +# → http://localhost:3008 +# 現在のソースからビルド +# docker compose up -d --build +``` + +**既存のデプロイを更新:** +```bash +git pull +docker compose pull && docker compose up -d +``` + 最初に登録したユーザーが自動的に**プラットフォーム管理者**になります。 ### ネットワークトラブルシューティング diff --git a/README_ko.md b/README_ko.md index bae4f8b26..7f6171b4a 100644 --- a/README_ko.md +++ b/README_ko.md @@ -92,6 +92,24 @@ bash restart.sh # 서비스 시작 > **참고:** `setup.sh`는 사용 가능한 PostgreSQL을 자동으로 감지합니다. 찾을 수 없는 경우 **로컬 인스턴스를 자동으로 다운로드하고 시작합니다**. 특정 PostgreSQL 인스턴스를 사용하려면 `.env` 파일에서 `DATABASE_URL`을 설정하세요. +### Docker + +```bash +git clone https://github.com/dataelement/Clawith.git +cd Clawith && cp .env.example .env +# GitHub Container Registry에서 미리 빌드된 이미지 다운로드 +docker compose up -d +# → http://localhost:3008 +# 현재 소스에서 빌드 +# docker compose up -d --build +``` + +**기존 배포 업데이트:** +```bash +git pull +docker compose pull && docker compose up -d +``` + 처음 등록한 사용자가 자동으로 **플랫폼 관리자**가 됩니다. ### 네트워크 문제 해결 diff --git a/README_zh-CN.md b/README_zh-CN.md index 5e867bc4c..b9d000c8e 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -108,14 +108,17 @@ bash restart.sh ```bash git clone https://github.com/dataelement/Clawith.git cd Clawith && cp .env.example .env +# 从 GitHub Container Registry 拉取预构建镜像 docker compose up -d # → http://localhost:3008 +# 改为从当前源码构建 +# docker compose up -d --build ``` **更新已有部署:** ```bash git pull -docker compose up -d --build +docker compose pull && docker compose up -d ``` > **🇨🇳 Docker 镜像加速(国内用户):** 如果 `docker compose up -d` 拉取镜像失败或超时,请先配置 Docker 镜像加速源: diff --git a/deploy/RELEASE_DEPLOYMENT.md b/deploy/RELEASE_DEPLOYMENT.md index ef13d2430..03c723ce3 100644 --- a/deploy/RELEASE_DEPLOYMENT.md +++ b/deploy/RELEASE_DEPLOYMENT.md @@ -19,12 +19,31 @@ owns CI validation, artifact transfer, and production deployment. - verify the proxied API health endpoint; - send a Feishu notification when the release succeeds or fails. 5. GitHub Actions publishes the GitHub Release and finishes without waiting for - Drone. Drone continues the deployment asynchronously and reports its status - on the tagged commit. + Drone. It also publishes multi-architecture backend and frontend images to + GitHub Container Registry. Drone continues the deployment asynchronously and + reports its status on the tagged commit. Only tags matching `refs/tags/v*` enter the Drone release pipeline. Branch pushes and pull requests still run CI, but never export or deploy images. +## Public container images + +Each GitHub Release published by this workflow produces `linux/amd64` and +`linux/arm64` images: + +- `ghcr.io/dataelement/clawith-backend:`; +- `ghcr.io/dataelement/clawith-frontend:`. + +The release GitHub identifies as latest also receives the `latest` tag. GHCR is +the only public registry written by the upstream release workflow. Image builds +use the release tag as their source and the existing Dockerfiles as their build +definitions. + +After the workflow creates each package for the first time, an organization +owner must set its visibility to public. Linking a package to this repository +grants the workflow access but does not set public visibility. Before announcing +the release, verify that both images can be pulled without GHCR authentication. + ## Drone configuration The repository must be trusted by Drone because the CI steps use privileged diff --git a/docker-compose.yml b/docker-compose.yml index 151fa1dea..1a28ae0ad 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,6 +30,7 @@ services: retries: 5 backend: + image: ghcr.io/dataelement/clawith-backend:latest build: context: ./backend args: @@ -91,6 +92,7 @@ services: max-size: "10m" max-file: "3" frontend: + image: ghcr.io/dataelement/clawith-frontend:latest build: ./frontend restart: unless-stopped ports: