mirror of
https://github.com/eznix86/registry-client.git
synced 2026-07-25 13:19:14 +00:00
Go Registry Client used By Docker Registry UI
- Go 99.6%
- Makefile 0.4%
| .github/workflows | ||
| jsoncompat | ||
| testdata | ||
| .gitignore | ||
| .golangci.json | ||
| .golangci.local.json | ||
| client.go | ||
| client_test.go | ||
| github.go | ||
| github_test.go | ||
| go.mod | ||
| go.sum | ||
| interface.go | ||
| interface_test.go | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| registry.go | ||
| registry_test.go | ||
| renovate.json | ||
| responses.go | ||
| types.go | ||
Registry Client
A Go client library for interacting with OCI/Docker container registries.
Used by Docker Registry UI
Features
- Full support for Docker Distribution API v2
- OCI and Docker manifest handling
- Built-in retry logic with exponential backoff
- Authentication support (Basic Auth and Bearer Token)
- Pagination support for large result sets
- Optional logging interface
- Health check endpoint
- GitHub Container Registry support (user and organization packages)
- Safe delete operations with
DisableDeleteflag for testing - uses
encoding/json/v2can be enabled usingGOEXPERIMENT=jsonv2
Installation
go get github.com/eznix86/registry-client
Usage
Basic Setup
import (
"net/http"
registryclient "github.com/eznix86/registry-client"
)
// Create a client with basic authentication
client := ®istryclient.BaseClient{
HTTPClient: &http.Client{},
BaseURL: "https://registry.example.com",
Auth: registryclient.BasicAuth{
Username: "user",
Password: "pass",
},
}
// Or with bearer token
client := ®istryclient.BaseClient{
HTTPClient: &http.Client{},
BaseURL: "https://registry.example.com",
Auth: registryclient.BearerAuth{
Token: "your-token",
},
}
Configuration Options
client := ®istryclient.BaseClient{
HTTPClient: &http.Client{},
BaseURL: "https://registry.example.com",
Auth: auth,
RetryBackoff: 200 * time.Millisecond, // Initial backoff duration
MaxAttempts: 3, // Maximum retry attempts
Logger: logger, // Optional logger implementation
}
Health Check
status, err := client.HealthCheck(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Registry status: %d\n", *status)
List Repositories
catalog, err := client.GetCatalog(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
for _, repo := range catalog.Repositories {
fmt.Println(repo)
}
List Tags
tags, err := client.ListTags(context.Background(), "my-repo", nil)
if err != nil {
log.Fatal(err)
}
for _, tag := range tags.Tags {
fmt.Println(tag)
}
Get Manifest
manifest, err := client.GetManifest(context.Background(), "my-repo", "latest")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Digest: %s\n", manifest.Digest)
fmt.Printf("Media Type: %s\n", manifest.MediaType)
Get Blob (Image Config)
blob, err := client.GetBlob(context.Background(), "my-repo", "sha256:abc123...")
if err != nil {
log.Fatal(err)
}
config, err := registryclient.ParseConfigBlob(blob.Content)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Architecture: %s\n", config.Architecture)
fmt.Printf("OS: %s\n", config.OS)
Pagination
// Get first page with 50 items
pagination := ®istryclient.PaginationParams{
N: 50,
}
catalog, err := client.GetCatalog(context.Background(), pagination)
if err != nil {
log.Fatal(err)
}
// Get next page
if catalog.HasMore {
pagination.Last = catalog.Last
next, err := client.GetCatalog(context.Background(), pagination)
// ...
}
Check Existence
// Check if manifest exists
exists, err := client.HasManifest(context.Background(), "my-repo", "latest")
if err != nil {
log.Fatal(err)
}
// Check if blob exists
exists, err = client.HasBlob(context.Background(), "my-repo", "sha256:abc123...")
if err != nil {
log.Fatal(err)
}
Delete Manifest
// Note: reference must be a digest, not a tag
err := client.DeleteManifest(context.Background(), "my-repo", "sha256:abc123...")
if err != nil {
log.Fatal(err)
}
Safe Delete Testing
Use DisableDelete flag to test delete operations without actually deleting resources:
client := ®istryclient.BaseClient{
HTTPClient: &http.Client{},
BaseURL: "https://registry.example.com",
DisableDelete: true, // Prevents actual deletion, only logs
}
// This will only log the delete operation, not execute it
err := client.DeleteManifest(context.Background(), "my-repo", "sha256:abc123...")
// No error, but nothing was deleted
GitHub Container Registry
For GitHub Container Registry (ghcr.io), use GitHubClient:
import registryclient "github.com/eznix86/registry-client"
// For user packages
// Note: Pass your GitHub Personal Access Token directly (plain text)
// It will be properly encoded for ghcr.io registry access and used plain for API calls
client := registryclient.NewGitHubClient("username", "ghp_yourtoken")
// List user's container packages
catalog, err := client.GetCatalog(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
for _, pkg := range catalog.Repositories {
fmt.Println(pkg)
}
// For organization packages
orgClient := registryclient.NewGitHubOrgClient("myorg", "ghp_yourtoken")
orgCatalog, err := orgClient.GetCatalog(context.Background(), nil)
if err != nil {
log.Fatal(err)
}
Custom Logger
Implement the Logger interface to add logging:
type Logger interface {
Debug(msg string, args ...any)
Info(msg string, args ...any)
Warn(msg string, args ...any)
Error(msg string, args ...any)
}
API Reference
BaseClient Methods
HealthCheck(ctx) (int, error)- Check registry availabilityGetCatalog(ctx, pagination) (*CatalogResponse, error)- List repositoriesListTags(ctx, repository, pagination) (*TagsResponse, error)- List tags for a repositoryGetManifest(ctx, repository, reference, acceptHeaders...) (*ManifestResponse, error)- Get image manifestHasManifest(ctx, repository, reference, acceptHeaders...) (bool, error)- Check if manifest existsGetBlob(ctx, repository, digest) (*BlobResponse, error)- Get blob contentHasBlob(ctx, repository, digest) (bool, error)- Check if blob existsDeleteManifest(ctx, repository, digest, acceptHeaders...) error- Delete manifest by digest
GitHubClient Methods
GitHubClient embeds BaseClient and provides the same methods, with special handling for:
GetCatalog(ctx, pagination)- Lists user or organization packages from GitHub APIDeleteManifest(ctx, repository, reference)- Deletes package versions (works with tags or digests)
Authentication
BasicAuth{Username, Password}- HTTP Basic AuthenticationBearerAuth{Token}- HTTP Bearer Token Authentication
Contributing
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests and ensure they pass
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development Guidelines
- Write clear, idiomatic Go code
- Add tests for new functionality
- Update documentation as needed
- Follow existing code style and conventions
- Ensure all tests pass before submitting PR
License
This project is licensed under the MIT License - see the LICENSE file for details.
Support
For issues and feature requests, please use the GitHub issue tracker.