mirror of
https://tangled.org/evan.jarrett.net/at-container-registry
synced 2026-08-29 20:27:16 +00:00
245 lines
5.3 KiB
Markdown
245 lines
5.3 KiB
Markdown
# ATCR - ATProto Container Registry
|
|
|
|
A container registry that uses the AT Protocol (ATProto) for manifest storage and S3 for blob storage.
|
|
|
|
## Overview
|
|
|
|
ATCR is an OCI-compliant container registry that integrates with the AT Protocol ecosystem. It stores container image manifests as ATProto records in Personal Data Servers (PDS) while keeping the actual image layers in S3-compatible storage.
|
|
|
|
### Architecture
|
|
|
|
- **Manifests**: Stored as ATProto records in user PDSs (small JSON metadata)
|
|
- **Blobs/Layers**: Stored in S3 (large binary data)
|
|
- **Name Resolution**: Supports both ATProto handles and DIDs
|
|
- `atcr.io/alice.bsky.social/myimage:latest`
|
|
- `atcr.io/did:plc:xyz123/myimage:latest`
|
|
|
|
## Features
|
|
|
|
- OCI Distribution Spec compliant
|
|
- ATProto-native manifest storage
|
|
- S3 blob storage for container layers
|
|
- DID/handle resolution
|
|
- Decentralized manifest ownership
|
|
|
|
## Building
|
|
|
|
```bash
|
|
# Build all binaries locally
|
|
go build -o atcr-appview ./cmd/appview
|
|
go build -o atcr-hold ./cmd/hold
|
|
go build -o docker-credential-atcr ./cmd/credential-helper
|
|
|
|
# Build Docker images
|
|
docker build -t atcr.io/appview:latest .
|
|
docker build -f Dockerfile.hold -t atcr.io/hold:latest .
|
|
```
|
|
|
|
## Quick Start (Local Testing)
|
|
|
|
**Automated setup:**
|
|
```bash
|
|
# Run the test script (handles everything)
|
|
./test-local.sh
|
|
```
|
|
|
|
The script will:
|
|
1. Create necessary directories (`/var/lib/atcr/*`)
|
|
2. Build all binaries
|
|
3. Start registry and hold service
|
|
4. Show you how to test
|
|
|
|
**Manual setup:**
|
|
```bash
|
|
# 1. Create directories
|
|
sudo mkdir -p /var/lib/atcr/{blobs,hold,auth}
|
|
sudo chown -R $USER:$USER /var/lib/atcr
|
|
|
|
# 2. Build binaries
|
|
go build -o atcr-appview ./cmd/appview
|
|
go build -o atcr-hold ./cmd/hold
|
|
|
|
# 3. Configure environment
|
|
cp .env.example .env
|
|
# Edit .env - set ATPROTO_HANDLE and HOLD_PUBLIC_URL
|
|
export $(cat .env | xargs)
|
|
|
|
# 4. Start services
|
|
# Terminal 1:
|
|
./atcr-appview serve config/config.yml
|
|
# Terminal 2 (will prompt for OAuth):
|
|
./atcr-hold config/hold.yml
|
|
# Follow OAuth URL in logs to authorize
|
|
|
|
# 5. Test with Docker
|
|
docker tag alpine:latest localhost:5000/alice/alpine:test
|
|
docker push localhost:5000/alice/alpine:test
|
|
docker pull localhost:5000/alice/alpine:test
|
|
```
|
|
|
|
## Running
|
|
|
|
### Local Development
|
|
|
|
**Configure environment:**
|
|
```bash
|
|
# Copy and edit .env file
|
|
cp .env.example .env
|
|
# Edit .env with:
|
|
# - ATPROTO_HANDLE (your Bluesky handle)
|
|
# - HOLD_PUBLIC_URL (e.g., http://127.0.0.1:8080 or https://hold1.atcr.io)
|
|
# - HOLD_AUTO_REGISTER=true
|
|
|
|
# Load environment
|
|
export $(cat .env | xargs)
|
|
```
|
|
|
|
**AppView:**
|
|
```bash
|
|
./atcr-appview serve config/config.yml
|
|
```
|
|
|
|
**Hold (Storage Service):**
|
|
```bash
|
|
# Starts OAuth flow to register in your PDS
|
|
./atcr-hold config/hold.yml
|
|
# Follow the OAuth URL in the logs to authorize
|
|
```
|
|
|
|
### Docker
|
|
|
|
**Run with Docker Compose:**
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
**Or run containers separately:**
|
|
|
|
**AppView:**
|
|
```bash
|
|
docker run -d \
|
|
--name atcr-appview \
|
|
-p 5000:5000 \
|
|
-e ATPROTO_DID=did:plc:your-did \
|
|
-e ATPROTO_ACCESS_TOKEN=your-access-token \
|
|
-e AWS_ACCESS_KEY_ID=your-aws-key \
|
|
-e AWS_SECRET_ACCESS_KEY=your-aws-secret \
|
|
-v $(pwd)/config/config.yml:/etc/atcr/config.yml \
|
|
atcr.io/appview:latest
|
|
```
|
|
|
|
**Hold (Storage Service):**
|
|
```bash
|
|
docker run -d \
|
|
--name atcr-hold \
|
|
-p 8080:8080 \
|
|
-e AWS_ACCESS_KEY_ID=your-aws-key \
|
|
-e AWS_SECRET_ACCESS_KEY=your-aws-secret \
|
|
-v $(pwd)/config/hold.yml:/etc/atcr/hold.yml \
|
|
atcr.io/hold:latest
|
|
```
|
|
|
|
### Kubernetes
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: atcr-appview
|
|
spec:
|
|
replicas: 3
|
|
selector:
|
|
matchLabels:
|
|
app: atcr-appview
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: atcr-appview
|
|
spec:
|
|
containers:
|
|
- name: appview
|
|
image: atcr.io/appview:latest
|
|
ports:
|
|
- containerPort: 5000
|
|
env:
|
|
- name: ATPROTO_DID
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: atcr-secrets
|
|
key: did
|
|
- name: ATPROTO_ACCESS_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: atcr-secrets
|
|
key: access-token
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /etc/atcr
|
|
volumes:
|
|
- name: config
|
|
configMap:
|
|
name: atcr-config
|
|
```
|
|
|
|
## Configuration
|
|
|
|
See `config/config.yml` for full configuration options.
|
|
|
|
Key settings:
|
|
- **storage.s3**: S3 bucket configuration for blob storage
|
|
- **middleware.repository**: ATProto routing middleware
|
|
- **middleware.registry**: Name resolution middleware
|
|
|
|
## Usage
|
|
|
|
### Pushing an Image
|
|
|
|
```bash
|
|
# Tag your image
|
|
docker tag myapp:latest atcr.io/alice/myapp:latest
|
|
|
|
# Push to ATCR
|
|
docker push atcr.io/alice/myapp:latest
|
|
```
|
|
|
|
### Pulling an Image
|
|
|
|
```bash
|
|
# Pull from ATCR
|
|
docker pull atcr.io/alice/myapp:latest
|
|
```
|
|
|
|
## Development
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
atcr.io/
|
|
├── cmd/appview/ # AppView entrypoint
|
|
├── pkg/
|
|
│ ├── atproto/ # ATProto client and manifest store
|
|
│ ├── storage/ # S3 blob store and routing
|
|
│ ├── middleware/ # Registry and repository middleware
|
|
│ └── server/ # HTTP handlers
|
|
├── config/ # Configuration files
|
|
└── Dockerfile
|
|
```
|
|
|
|
### Testing
|
|
|
|
```bash
|
|
# Run tests
|
|
go test ./...
|
|
|
|
# Run with race detector
|
|
go test -race ./...
|
|
```
|
|
|
|
## License
|
|
|
|
MIT
|
|
|
|
## Contributing
|
|
|
|
Contributions welcome! Please open an issue or PR.
|