feat: add registry config, image upload/download, and OCI format support

Backend:
- Add registry_address configuration API (GET/POST)
- Add tar image upload with OCI and Docker format support
- Add image download with streaming optimization
- Fix blob download using c.Send (Fiber v3 SendStream bug)
- Add registry_address prefix stripping for all OCI v2 endpoints
- Add AGENTS.md for project documentation

Frontend:
- Add settings store with Snackbar notifications
- Add image upload dialog with progress bar
- Add download state tracking with multi-stage feedback
- Replace alert() with MUI Snackbar messages
- Display image names without registry_address prefix

🤖 Generated with [Qoder](https://qoder.com)
This commit is contained in:
loveuer
2025-11-10 16:28:58 +08:00
parent 29088a6b54
commit 9780a2b028
35 changed files with 3065 additions and 91 deletions

167
AGENTS.md Normal file
View File

@@ -0,0 +1,167 @@
# AGENTS.md
This file provides guidance to Qoder (qoder.com) when working with code in this repository.
## Project Overview
Cluster is a lightweight OCI (Open Container Initiative) registry implementation with a Go backend (Fiber v3) and React/TypeScript frontend. It provides Docker registry v2 API compliance for container image storage and management.
## Build and Development Commands
### Backend (Go)
```bash
# Build the binary
go build -o cluster .
# Run with default settings
./cluster
# Run with custom configuration
./cluster -debug -address 0.0.0.0:8080 -data-dir ./x-storage
# Run tests
go test ./pkg/tool/...
# Update dependencies
go mod tidy
```
**Command-line flags:**
- `-debug`: Enable debug logging
- `-address` / `-A`: Server listen address (default: 0.0.0.0:9119)
- `-data-dir` / `-D`: Data directory for storage (default: ./x-storage)
### Frontend (React/TypeScript)
**Package Manager:** This project uses `pnpm` exclusively. Do not use npm or yarn.
```bash
cd frontend
# Install dependencies
pnpm install
# Development server (runs on http://localhost:3000)
pnpm dev
# Lint TypeScript/React code
pnpm lint
# Production build
pnpm run build
# Preview production build
pnpm preview
```
### Full Stack Development
```bash
# Run both backend and frontend concurrently
./dev.sh
```
The `dev.sh` script starts the Go backend and Vite dev server together, handling graceful shutdown on Ctrl+C.
## Architecture
### Request Flow
1. **Entry Point** (`main.go`): Initializes signal handling and delegates to cobra command
2. **Command Layer** (`internal/cmd/cmd.go`): Manages application lifecycle
- Initializes configuration (`internal/opt`)
- Initializes SQLite database (`pkg/database/db`) at `{data-dir}/cluster.db`
- Initializes filesystem storage (`pkg/store`) for blobs/manifests
- Starts Fiber HTTP server (`internal/api`)
3. **API Layer** (`internal/api/api.go`): Routes requests to handlers
- OCI Registry v2 endpoints: `/v2/*` routes to `internal/module/registry`
- Custom API v1 endpoints: `/api/v1/registry/*` for image listing and config
4. **Handler Layer** (`internal/module/registry/`): Implements OCI registry operations
- `registry.go`: Main routing logic
- `blob.go`: Blob upload/download/chunked upload
- `manifest.go`: Manifest storage and retrieval
- `tag.go`: Tag management
- `catalog.go`: Repository listing
### Storage Architecture
**Database** (`pkg/database/db`):
- SQLite via GORM
- Stores: repositories, tags, manifest metadata, registry config
- Location: `{data-dir}/cluster.db`
**Filesystem Storage** (`pkg/store`):
- Content-addressed storage with SHA256
- Structure:
- `registry/blobs/sha256/{2-char-prefix}/{2-char-prefix}/{full-hash}` - Blob files
- `registry/manifests/sha256/{2-char-prefix}/{2-char-prefix}/{full-hash}` - Manifest files
- `registry/uploads/{uuid}` - Temporary upload files
- All write operations verify SHA256 digest before finalizing
### Frontend Architecture
**Tech Stack:**
- React 18 + TypeScript
- Vite build tool
- Zustand state management (`src/stores/`)
- Material-UI (MUI) components
- React Router for routing
**API Proxy:** Dev server proxies `/api/*` requests to backend (configured in `vite.config.ts`)
### Key Packages
- `pkg/tool/`: Utility functions (UUID generation, password hashing, file helpers, table formatting, etc.)
- `pkg/resp/`: HTTP response helpers and i18n
- `internal/middleware/`: CORS, logging, recovery, repository context injection
- `internal/model/`: GORM database models
## Code Conventions
### Go
- Use GORM for database operations via `db.Default` singleton
- Use `pkg/store.Default` for filesystem operations
- Handlers receive `(ctx context.Context, db *gorm.DB, store store.Store)` and return `fiber.Handler`
- Middleware uses Fiber v3 context
- Digest format is always `sha256:hexstring`
- All blob/manifest writes must verify digest before finalizing
### Frontend
- Use Zustand for state management
- Follow MUI theming patterns defined in `src/theme.ts`
- TypeScript strict mode enabled
- Components in `src/components/`, pages in `src/pages/`
## Testing
```bash
# Run Go tests
go test ./pkg/tool/...
# Frontend linting (no test framework currently configured)
cd frontend && pnpm lint
```
## OCI Registry v2 API Endpoints
- `GET /v2/` - Registry version check
- `POST /v2/{repo}/blobs/uploads/` - Initiate blob upload, returns upload UUID
- `PATCH /v2/{repo}/blobs/uploads/{uuid}` - Upload blob chunk (chunked upload)
- `PUT /v2/{repo}/blobs/uploads/{uuid}?digest={digest}` - Finalize blob upload
- `GET /v2/{repo}/blobs/{digest}` - Download blob
- `HEAD /v2/{repo}/blobs/{digest}` - Check blob existence
- `PUT /v2/{repo}/manifests/{tag}` - Store manifest
- `GET /v2/{repo}/manifests/{tag}` - Retrieve manifest
- `DELETE /v2/{repo}/manifests/{tag}` - Delete manifest
- `GET /v2/{repo}/tags/list` - List repository tags
- `GET /v2/_catalog` - List all repositories
## Custom API v1 Endpoints
- `GET /api/v1/registry/image/list` - List images with metadata
- `GET /api/v1/registry/image/download/*` - Download images
- `GET /api/v1/registry/config` - Get registry configuration
- `POST /api/v1/registry/config` - Set registry configuration