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:
167
AGENTS.md
Normal file
167
AGENTS.md
Normal 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
|
||||
Reference in New Issue
Block a user