Overview
Container registries serve as centralized repositories for container images, analogous to version control systems for source code but specialized for binary artifacts. A container registry stores images as layers with associated metadata, tags, and manifests that describe image composition and dependencies.
The registry acts as the distribution mechanism in containerized workflows. Developers push built images to the registry after local development. CI/CD pipelines pull images for testing, scanning, and deployment. Production environments retrieve images to launch containers. This push-pull model decouples image creation from consumption, enabling consistent deployments across environments.
Docker Hub pioneered the public registry model in 2013, but organizations quickly recognized the need for private registries. Modern container ecosystems support both public registries for open-source distribution and private registries for proprietary applications. The Open Container Initiative (OCI) standardized the distribution specification in 2015, ensuring interoperability between registry implementations.
A registry organizes images hierarchically. At the top level, repositories group related images under a namespace. Within a repository, tags identify specific image versions. The same image content may have multiple tags (latest, v1.2.3, stable). Beneath tags, the manifest describes layer composition, while layers contain the actual filesystem changes.
# Registry URL structure
# registry_host/namespace/repository:tag
# docker.io/library/ruby:3.2-alpine
# ghcr.io/myorg/myapp:v1.0.0
registry = "ghcr.io"
namespace = "myorg"
repository = "api-service"
tag = "2024.10.1"
full_image = "#{registry}/#{namespace}/#{repository}:#{tag}"
# => "ghcr.io/myorg/api-service:2024.10.1"
Container registries handle authentication, authorization, and API access. The Docker Registry HTTP API V2 defines standard endpoints for pushing, pulling, and querying images. Authentication methods range from basic credentials to OAuth tokens to cloud provider IAM integration.
Key Principles
Image Immutability: Container images in registries are immutable. Once pushed with a specific digest (content hash), that image cannot change. Tags are mutable pointers to immutable images. Pushing a new image with an existing tag updates the tag reference but preserves the original image.
# Same tag, different images over time
# 2024-01-15: myapp:latest -> sha256:abc123...
# 2024-02-20: myapp:latest -> sha256:def456...
# The digest uniquely identifies content
image_by_tag = "myapp:latest" # mutable reference
image_by_digest = "myapp@sha256:abc123..." # immutable reference
Content Addressability: Registries identify images by cryptographic hashes of their content. The digest (typically SHA256) serves as a unique identifier independent of tags or repository names. This prevents tampering and ensures reproducible deployments.
Layered Storage: Container images consist of read-only layers stacked on each other. Registries store layers independently, deduplicating common layers across images. When pulling an image, the registry transmits only layers not already present on the client.
# Image layers represent filesystem changes
class ImageManifest
attr_reader :layers, :config
def initialize
@layers = []
@config = {}
end
def add_layer(digest, size, media_type)
@layers << {
digest: digest,
size: size,
mediaType: media_type
}
end
def total_size
@layers.sum { |layer| layer[:size] }
end
end
manifest = ImageManifest.new
manifest.add_layer("sha256:abc123", 5_242_880, "application/vnd.docker.image.rootfs.diff.tar.gzip")
manifest.add_layer("sha256:def456", 1_048_576, "application/vnd.docker.image.rootfs.diff.tar.gzip")
# Total download: 6_291_456 bytes, but shared layers skip download
Namespace Isolation: Registries partition images into namespaces preventing naming conflicts. Public registries use user or organization names as namespaces. Private registries may map namespaces to teams, projects, or environments.
Manifest Format: The image manifest describes layer composition, configuration, and platform compatibility. Manifests follow OCI standards, specifying layer order, compression types, and architecture requirements. Multi-platform images use manifest lists containing platform-specific manifests.
Push-Pull Protocol: The registry API defines distinct workflows for pushing and pulling images. Pulling requires fewer operations (manifest retrieval, layer downloads). Pushing involves layer existence checks, blob uploads, and manifest submission. Both operations use content negotiation to handle format variations.
Garbage Collection: Deleted tags don't immediately remove underlying layers. Registries perform garbage collection to reclaim storage from unreferenced layers. Some implementations require manual garbage collection, while others run automatically on schedules.
Ruby Implementation
Ruby applications interact with container registries through HTTP clients and specialized gems. The docker-api gem provides high-level abstractions, while net/http handles direct registry API communication for custom workflows.
require 'docker-api'
require 'json'
# Configure Docker client to use specific registry
Docker.url = 'unix:///var/run/docker.sock'
Docker.options = {
read_timeout: 300,
write_timeout: 300
}
# Pull image from registry
image = Docker::Image.create('fromImage' => 'ruby:3.2-alpine')
puts "Image ID: #{image.id}"
puts "Size: #{image.info['Size']} bytes"
# => Image ID: sha256:a1b2c3d4...
# => Size: 52428800 bytes
# Tag image for private registry
image.tag(
repo: 'registry.example.com/myapp/ruby',
tag: '3.2-alpine-custom',
force: true
)
Authentication with private registries requires credentials passed to Docker operations or stored in configuration files:
require 'docker-api'
require 'base64'
# Authenticate with registry
auth_config = {
username: ENV['REGISTRY_USER'],
password: ENV['REGISTRY_PASSWORD'],
serveraddress: 'registry.example.com'
}
# Push image with authentication
image = Docker::Image.get('myapp:latest')
image.push(auth_config) do |chunk|
parsed = JSON.parse(chunk)
puts parsed['status'] if parsed['status']
end
Direct registry API interaction using net/http for operations not covered by docker-api:
require 'net/http'
require 'json'
require 'base64'
class RegistryClient
def initialize(registry_url, username, password)
@registry_url = registry_url
@auth = Base64.strict_encode64("#{username}:#{password}")
end
def get_tags(repository)
uri = URI("#{@registry_url}/v2/#{repository}/tags/list")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Basic #{@auth}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
JSON.parse(response.body)
end
def get_manifest(repository, tag)
uri = URI("#{@registry_url}/v2/#{repository}/manifests/#{tag}")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = "Basic #{@auth}"
request['Accept'] = 'application/vnd.docker.distribution.manifest.v2+json'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
{
manifest: JSON.parse(response.body),
digest: response['Docker-Content-Digest']
}
end
def delete_manifest(repository, digest)
uri = URI("#{@registry_url}/v2/#{repository}/manifests/#{digest}")
request = Net::HTTP::Delete.new(uri)
request['Authorization'] = "Basic #{@auth}"
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
response.code == '202'
end
end
# Usage
client = RegistryClient.new('https://registry.example.com', 'admin', 'password')
tags = client.get_tags('myapp/api')
puts "Available tags: #{tags['tags'].join(', ')}"
manifest_data = client.get_manifest('myapp/api', 'v1.0.0')
puts "Digest: #{manifest_data[:digest]}"
puts "Layers: #{manifest_data[:manifest]['layers'].length}"
Ruby applications building images programmatically can use dockerfile-ruby gem or invoke Docker build via shell:
require 'open3'
class ImageBuilder
def self.build_and_push(context_dir, image_name, tag)
full_tag = "#{image_name}:#{tag}"
# Build image
build_cmd = "docker build -t #{full_tag} #{context_dir}"
stdout, stderr, status = Open3.capture3(build_cmd)
raise "Build failed: #{stderr}" unless status.success?
# Extract image ID from output
image_id = stdout.match(/Successfully built (\w+)/)[1]
# Push to registry
push_cmd = "docker push #{full_tag}"
stdout, stderr, status = Open3.capture3(push_cmd)
raise "Push failed: #{stderr}" unless status.success?
{ image_id: image_id, tag: full_tag }
end
end
result = ImageBuilder.build_and_push('./app', 'registry.example.com/myapp', 'v2.1.0')
puts "Built and pushed: #{result[:tag]}"
Implementation Approaches
Self-Hosted Registry: Organizations deploy registry software on their infrastructure for complete control. Docker Registry (open-source) and Harbor (CNCF project) are common choices. Self-hosting requires managing storage backends, implementing backup strategies, and maintaining high availability.
# Docker Registry deployment configuration
registry_config = {
version: '0.1',
storage: {
filesystem: {
rootdirectory: '/var/lib/registry'
},
delete: {
enabled: true
}
},
http: {
addr: ':5000',
secret: ENV['REGISTRY_HTTP_SECRET']
},
auth: {
htpasswd: {
realm: 'Registry Realm',
path: '/auth/htpasswd'
}
}
}
# Save configuration for deployment
require 'yaml'
File.write('registry-config.yml', registry_config.to_yaml)
Self-hosted registries integrate with existing storage systems. Backends include local filesystems, NFS, S3-compatible object storage, Azure Blob Storage, and Google Cloud Storage. Storage drivers handle layer persistence, deduplication, and retrieval.
Cloud-Managed Registry: Cloud providers offer managed registry services eliminating infrastructure management. AWS Elastic Container Registry (ECR), Google Container Registry (GCR), and Azure Container Registry (ACR) provide scalable storage, integrated authentication, and vulnerability scanning.
require 'aws-sdk-ecr'
class ECRManager
def initialize(region)
@client = Aws::ECR::Client.new(region: region)
end
def create_repository(name)
@client.create_repository({
repository_name: name,
image_scanning_configuration: {
scan_on_push: true
},
encryption_configuration: {
encryption_type: 'AES256'
}
})
end
def get_login_password
response = @client.get_authorization_token
token = response.authorization_data.first.authorization_token
Base64.decode64(token).split(':').last
end
def list_images(repository_name)
@client.list_images({
repository_name: repository_name
}).image_ids.map(&:image_tag)
end
end
ecr = ECRManager.new('us-east-1')
ecr.create_repository('myapp/api')
password = ecr.get_login_password
# Use password for docker login
Cloud registries handle authentication through IAM policies. Applications authenticate using cloud credentials rather than registry-specific passwords. Cross-region replication distributes images globally for faster pulls.
Distributed Registry Architecture: Large organizations deploy multiple registry instances across regions or availability zones. Replication keeps images synchronized. Traffic routing directs pulls to nearby registries reducing latency.
class RegistryReplicator
def initialize(source_registry, target_registries)
@source = source_registry
@targets = target_registries
end
def replicate_image(repository, tag)
# Pull from source
source_image = "#{@source}/#{repository}:#{tag}"
system("docker pull #{source_image}")
# Push to all targets
@targets.each do |target|
target_image = "#{target}/#{repository}:#{tag}"
system("docker tag #{source_image} #{target_image}")
system("docker push #{target_image}")
end
end
def sync_repository(repository)
# Get all tags from source
tags = get_tags(@source, repository)
tags.each do |tag|
replicate_image(repository, tag)
end
end
private
def get_tags(registry, repository)
# Implementation using registry API
[]
end
end
replicator = RegistryReplicator.new(
'registry.us-east-1.example.com',
[
'registry.eu-west-1.example.com',
'registry.ap-south-1.example.com'
]
)
Proxy Registry: Proxy registries cache images from upstream registries reducing external bandwidth and improving pull performance. Docker Registry supports pull-through cache mode. Harbor provides proxy projects.
Embedded Registry: Development environments may run registries locally. Minikube and Kind (Kubernetes in Docker) include built-in registries for testing. Local registries accelerate inner development loops avoiding network transfers.
Security Implications
Image Vulnerability Scanning: Registries scan image layers for known vulnerabilities in packages and libraries. Scanners compare installed packages against CVE databases. Trivy, Clair, and Anchore are common scanning engines integrated into registry platforms.
require 'json'
require 'open3'
class ImageScanner
def self.scan_with_trivy(image_name)
cmd = "trivy image --format json #{image_name}"
stdout, stderr, status = Open3.capture3(cmd)
raise "Scan failed: #{stderr}" unless status.success?
results = JSON.parse(stdout)
vulnerabilities = results['Results'].flat_map do |result|
(result['Vulnerabilities'] || []).map do |vuln|
{
package: vuln['PkgName'],
severity: vuln['Severity'],
cve_id: vuln['VulnerabilityID'],
fixed_version: vuln['FixedVersion']
}
end
end
{
total: vulnerabilities.length,
critical: vulnerabilities.count { |v| v[:severity] == 'CRITICAL' },
high: vulnerabilities.count { |v| v[:severity] == 'HIGH' },
vulnerabilities: vulnerabilities
}
end
end
scan_result = ImageScanner.scan_with_trivy('myapp:latest')
puts "Total vulnerabilities: #{scan_result[:total]}"
puts "Critical: #{scan_result[:critical]}, High: #{scan_result[:high]}"
Organizations block deployment of images exceeding vulnerability thresholds. Admission controllers in Kubernetes can enforce policies requiring scanned, approved images.
Access Control: Registries implement role-based access control (RBAC) for repositories. Permissions include read (pull), write (push), delete, and admin. Cloud registries integrate with IAM systems. Harbor provides project-based isolation with fine-grained permissions.
class RegistryAccessControl
ROLES = {
developer: ['pull', 'push'],
operator: ['pull'],
admin: ['pull', 'push', 'delete', 'admin']
}
def initialize
@user_roles = {}
end
def grant_role(user, repository, role)
@user_roles[user] ||= {}
@user_roles[user][repository] = role
end
def can_perform?(user, repository, action)
role = @user_roles.dig(user, repository)
return false unless role
ROLES[role].include?(action)
end
def audit_log(user, repository, action, success)
{
timestamp: Time.now.iso8601,
user: user,
repository: repository,
action: action,
success: success
}
end
end
acl = RegistryAccessControl.new
acl.grant_role('alice', 'myapp/api', :developer)
acl.grant_role('bob', 'myapp/api', :operator)
puts acl.can_perform?('alice', 'myapp/api', 'push') # => true
puts acl.can_perform?('bob', 'myapp/api', 'push') # => false
Content Trust: Docker Content Trust (DCT) uses digital signatures to verify image publishers and integrity. Notary implements The Update Framework (TUF) for cryptographic verification. Signed images prevent tampering during transmission and storage.
Network Security: Registries require TLS encryption for all traffic. Certificate management ensures valid, trusted certificates. Private registries often sit behind VPNs or require VPC connectivity.
Credential Management: Registry credentials need secure storage. Environment variables, secret management systems (Vault, AWS Secrets Manager), or Kubernetes secrets store credentials. Avoid hardcoding credentials in application code or configuration files committed to version control.
require 'vault'
class SecureRegistryAuth
def self.get_credentials
Vault.address = ENV['VAULT_ADDR']
Vault.token = ENV['VAULT_TOKEN']
secret = Vault.logical.read('secret/data/registry')
credentials = secret.data[:data]
{
username: credentials[:username],
password: credentials[:password],
registry: credentials[:registry]
}
rescue Vault::VaultError => e
raise "Failed to retrieve credentials: #{e.message}"
end
def self.rotate_credentials(new_password)
Vault.logical.write(
'secret/data/registry',
data: {
username: 'service-account',
password: new_password,
registry: 'registry.example.com',
rotated_at: Time.now.iso8601
}
)
end
end
Supply Chain Security: Registries participate in software supply chain security. Organizations verify base image sources, scan dependencies, and maintain image provenance. SLSA (Supply-chain Levels for Software Artifacts) framework provides guidelines for securing build and distribution pipelines.
Tools & Ecosystem
Docker Registry: The reference implementation of OCI Distribution Specification. Open-source, lightweight, supports S3, Azure, and GCS storage backends. Limited built-in security features require external authentication and authorization systems.
Harbor: CNCF graduated project providing enterprise registry features. Includes vulnerability scanning with Trivy, replication, content signing, and RBAC. Web UI simplifies management. Robot accounts enable CI/CD integration.
require 'faraday'
require 'json'
class HarborClient
def initialize(url, username, password)
@conn = Faraday.new(url: url) do |f|
f.request :basic_auth, username, password
f.adapter Faraday.default_adapter
end
end
def list_projects
response = @conn.get('/api/v2.0/projects')
JSON.parse(response.body)
end
def create_project(name, public: false)
payload = {
project_name: name,
public: public,
metadata: {
auto_scan: 'true',
severity: 'high'
}
}
@conn.post('/api/v2.0/projects') do |req|
req.headers['Content-Type'] = 'application/json'
req.body = payload.to_json
end
end
def get_scan_results(project, repository, tag)
path = "/api/v2.0/projects/#{project}/repositories/#{repository}/artifacts/#{tag}/additions/vulnerabilities"
response = @conn.get(path)
JSON.parse(response.body)
end
end
harbor = HarborClient.new('https://harbor.example.com', 'admin', 'password')
projects = harbor.list_projects
puts "Projects: #{projects.map { |p| p['name'] }.join(', ')}"
Cloud Provider Registries: AWS ECR, Google Container Registry (GCR)/Artifact Registry, Azure Container Registry (ACR). Deep integration with cloud platforms, managed infrastructure, built-in vulnerability scanning, and IAM authentication.
GitHub Container Registry (ghcr.io): Integrated with GitHub repositories. Free for public images, included in GitHub plans for private images. Supports GitHub Actions workflows for automated image builds and pushes.
GitLab Container Registry: Built into GitLab. Tight integration with GitLab CI/CD. Project-level registries with inheritance from group settings.
Artifactory: JFrog Artifactory provides universal artifact management including container images. Advanced features include promotion workflows, property-based searches, and comprehensive audit logs.
Registry Proxies and Caches: Docker Registry supports pull-through caching. Companies deploy proxy registries to cache Docker Hub and other public registries reducing external bandwidth and improving availability during outages.
Image Building Tools: Buildah, Kaniko, and BuildKit provide alternatives to Docker for building images. These tools integrate with registries for pushing built images.
Image Analysis Tools: Dive analyzes layer efficiency, Skopeo copies images between registries without Docker daemon, Cosign signs and verifies images for supply chain security.
Real-World Applications
CI/CD Pipeline Integration: Modern continuous integration systems build container images and push to registries as artifacts. Pipelines pull base images, execute builds, tag results with build numbers or commit SHAs, and push to staging or production registries.
class CIPipeline
def initialize(registry, repository)
@registry = registry
@repository = repository
end
def execute_build(git_sha, branch)
# Build image
image_tag = generate_tag(git_sha, branch)
build_context = './app'
build_cmd = "docker build -t #{@registry}/#{@repository}:#{image_tag} #{build_context}"
unless system(build_cmd)
raise "Build failed for #{image_tag}"
end
# Tag with multiple identifiers
tags = [
image_tag, # SHA-based
branch.gsub('/', '-'), # Branch name
branch == 'main' ? 'latest' : nil # Latest for main
].compact
tags.each do |tag|
system("docker tag #{@registry}/#{@repository}:#{image_tag} #{@registry}/#{@repository}:#{tag}")
system("docker push #{@registry}/#{@repository}:#{tag}")
end
# Scan for vulnerabilities
scan_result = scan_image("#{@registry}/#{@repository}:#{image_tag}")
if scan_result[:critical] > 0
raise "Critical vulnerabilities found: #{scan_result[:critical]}"
end
{
image: "#{@registry}/#{@repository}:#{image_tag}",
tags: tags,
scan: scan_result
}
end
private
def generate_tag(git_sha, branch)
timestamp = Time.now.strftime('%Y%m%d-%H%M%S')
"#{branch.gsub('/', '-')}-#{git_sha[0..7]}-#{timestamp}"
end
def scan_image(image)
# Scan implementation
{ critical: 0, high: 2, medium: 5 }
end
end
pipeline = CIPipeline.new('registry.example.com', 'myapp/api')
result = pipeline.execute_build('a1b2c3d4', 'feature/auth')
puts "Published: #{result[:tags].join(', ')}"
Kubernetes Deployment: Kubernetes clusters pull container images from registries during pod creation. Image pull secrets authenticate with private registries. Clusters cache pulled images on nodes reducing registry load for frequently used images.
require 'yaml'
class K8sDeploymentGenerator
def self.generate(name, image, replicas: 3)
deployment = {
'apiVersion' => 'apps/v1',
'kind' => 'Deployment',
'metadata' => {
'name' => name,
'labels' => { 'app' => name }
},
'spec' => {
'replicas' => replicas,
'selector' => {
'matchLabels' => { 'app' => name }
},
'template' => {
'metadata' => {
'labels' => { 'app' => name }
},
'spec' => {
'imagePullSecrets' => [
{ 'name' => 'registry-credentials' }
],
'containers' => [{
'name' => name,
'image' => image,
'imagePullPolicy' => 'Always',
'ports' => [{ 'containerPort' => 8080 }]
}]
}
}
}
}
deployment.to_yaml
end
end
yaml = K8sDeploymentGenerator.generate(
'api-service',
'registry.example.com/myapp/api:v2.1.0'
)
puts yaml
Multi-Region Deployments: Organizations replicate images across geographic regions for redundancy and performance. Applications in different regions pull from local registries reducing latency. Replication jobs synchronize images between regions after builds complete.
Development Environment Standardization: Teams share development environment images via registries. Developers pull standardized images with pre-installed tools, dependencies, and configurations ensuring consistent development environments.
Microservices Architecture: Each microservice has its own repository in the registry. Service teams independently build, test, and deploy services. Service mesh systems pull images during rollouts and scaling operations.
Image Promotion Workflows: Organizations implement promotion workflows moving images through environments. Builds push to development registry/tag. Tests pull and validate. Successful tests promote images to staging then production through tag updates or cross-registry copying.
class ImagePromoter
def initialize(source_registry, target_registry)
@source = source_registry
@target = target_registry
end
def promote(repository, source_tag, target_tag, run_tests: true)
source_image = "#{@source}/#{repository}:#{source_tag}"
target_image = "#{@target}/#{repository}:#{target_tag}"
# Pull source image
system("docker pull #{source_image}") or raise "Pull failed"
# Run tests if required
if run_tests
test_result = run_integration_tests(source_image)
raise "Tests failed" unless test_result[:passed]
end
# Tag and push to target
system("docker tag #{source_image} #{target_image}")
system("docker push #{target_image}")
{
promoted_from: source_image,
promoted_to: target_image,
timestamp: Time.now
}
end
private
def run_integration_tests(image)
# Run tests against image
{ passed: true, duration: 45.2 }
end
end
promoter = ImagePromoter.new(
'registry-dev.example.com',
'registry-prod.example.com'
)
result = promoter.promote('myapp/api', 'dev-latest', 'v2.1.0')
Reference
Registry API Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
| /v2/ | GET | Check registry version and availability |
| /v2/_catalog | GET | List all repositories |
| /v2/name/tags/list | GET | List tags for repository |
| /v2/name/manifests/reference | GET | Retrieve image manifest |
| /v2/name/manifests/reference | PUT | Upload image manifest |
| /v2/name/manifests/reference | DELETE | Delete manifest by tag or digest |
| /v2/name/blobs/digest | GET | Download layer blob |
| /v2/name/blobs/digest | HEAD | Check blob existence |
| /v2/name/blobs/uploads/ | POST | Initiate blob upload |
| /v2/name/blobs/uploads/uuid | PATCH | Upload blob chunk |
| /v2/name/blobs/uploads/uuid | PUT | Complete blob upload |
Common Registry Ports
| Port | Protocol | Usage |
|---|---|---|
| 5000 | HTTP | Default Docker Registry port |
| 443 | HTTPS | Production registry with TLS |
| 80 | HTTP | Insecure registry (development only) |
Image Tag Strategies
| Strategy | Example | Use Case |
|---|---|---|
| Semantic Version | v1.2.3 | Release versions |
| Git SHA | a1b2c3d | Traceability to source |
| Build Number | build-1234 | CI/CD tracking |
| Branch Name | feature-auth | Development branches |
| Timestamp | 20241010-143022 | Time-based tracking |
| Latest | latest | Current default version |
| Environment | staging, production | Environment-specific |
| Combined | v1.2.3-a1b2c3d | Version with commit reference |
Storage Backend Comparison
| Backend | Scalability | Cost | Availability | Use Case |
|---|---|---|---|---|
| Local Filesystem | Low | Lowest | Single node | Development, testing |
| NFS | Medium | Low | Depends on NFS | Small deployments |
| S3/Compatible | High | Medium | Multi-region | Production, cloud-native |
| Azure Blob | High | Medium | Multi-region | Azure environments |
| GCS | High | Medium | Multi-region | Google Cloud environments |
Authentication Methods
| Method | Security | Complexity | Use Case |
|---|---|---|---|
| Basic Auth | Low | Low | Development |
| Token Auth | Medium | Medium | Production |
| OAuth2 | High | High | Enterprise SSO |
| IAM Integration | High | Medium | Cloud deployments |
| Certificate Auth | High | High | Mutual TLS requirements |
Manifest Media Types
| Type | Format | Purpose |
|---|---|---|
| application/vnd.docker.distribution.manifest.v2+json | Docker V2 | Single-platform image |
| application/vnd.docker.distribution.manifest.list.v2+json | Manifest List | Multi-platform images |
| application/vnd.oci.image.manifest.v1+json | OCI | OCI image format |
| application/vnd.oci.image.index.v1+json | OCI Index | OCI multi-platform |
Common Status Codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Operation completed |
| 201 | Created | Upload successful |
| 202 | Accepted | Manifest deleted |
| 401 | Unauthorized | Check credentials |
| 404 | Not Found | Verify repository/tag exists |
| 409 | Conflict | Tag already exists |
| 500 | Server Error | Check registry logs |
Ruby Gems for Registry Operations
| Gem | Purpose | Key Features |
|---|---|---|
| docker-api | Docker client | Image pull, push, build operations |
| aws-sdk-ecr | AWS ECR integration | ECR repository management |
| google-cloud-container_analysis | GCP integration | Vulnerability scanning results |
| azure_mgmt_container_registry | Azure ACR | ACR resource management |
Vulnerability Severity Levels
| Severity | CVSS Score | Action Required |
|---|---|---|
| Critical | 9.0-10.0 | Immediate remediation |
| High | 7.0-8.9 | Remediate within days |
| Medium | 4.0-6.9 | Remediate within weeks |
| Low | 0.1-3.9 | Review and schedule |
| Negligible | 0.0 | No action required |
Image Pull Policy Options
| Policy | Behavior | Use Case |
|---|---|---|
| Always | Pull on every pod creation | Development, latest tags |
| IfNotPresent | Pull only if not cached | Stable versions |
| Never | Only use cached images | Air-gapped environments |