[Registry](distribution.github.io/distribution/)是业界广泛使用的容器镜像托管软件,Registry被Docker捐献给CNCF之后,更名为Distribution。
Registry支持使用本地磁盘、对象存储(S3协议)作为后端存储,配置示例
```yaml
storage:
filesystem:
rootdirectory: /var/lib/registry
s3:
accesskey: awsaccesskey
secretkey: awssecretkey
region: us-west-1
regionendpoint: myobjects.local
forcepathstyle: true
accelerate: false
bucket: bucketname
encrypt: true
keyid: mykeyid
secure: true
v4auth: true
chunksize: 5242880
multipartcopychunksize: 33554432
multipartcopymaxconcurrency: 100
multipartcopythresholdsize: 33554432
rootdirectory: /s3/object/name/prefix
loglevel: debug
inmemory:
delete:
enabled: false
cache:
blobdescriptor: inmemory
blobdescriptorsize: 10000
maintenance:
uploadpurging:
enabled: true
age: 168h
interval: 24h
dryrun: false
readonly:
enabled: false
redirect:
disable: false
```
其中 `redirect.disable` 控制拉取镜像时是否直接从存储后端下载,比如使用S3, `redirect.disable`设置为 false`时将会从对象存储直接下载镜像层文件。
```
redirect:
disable: true
```
拉取镜像时,Registry会返回`307`并把镜像层文件地址放在Header `Location`中,为通过S3协议从对象存储获取的预签名的文件下载地址。
```go
// registry/storage/driver/s3-aws/s3.go
// URLFor returns a URL which may be used to retrieve the content stored at the given path.
// May return an UnsupportedMethodErr in certain StorageDriver implementations.
func (d *driver) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) {
methodString := "GET"
method, ok := options["method"]
if ok {
methodString, ok = method.(string)
if !ok || (methodString != "GET" && methodString != "HEAD") {
return "", storagedriver.ErrUnsupportedMethod{}
}
}
expiresIn := 20 * time.Minute
expires, ok := options["expiry"]
if ok {
et, ok := expires.(time.Time)
if ok {
expiresIn = time.Until(et)
}
}
var req *request.Request
source, ok := options["X-Crs-Source"]
switch methodString {
case "GET":
req, _ = d.S3.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String(d.Bucket),
Key: aws.String(d.s3Path(path)),
})
case "HEAD":
req, _ = d.S3.HeadObjectRequest(&s3.HeadObjectInput{
Bucket: aws.String(d.Bucket),
Key: aws.String(d.s3Path(path)),
})
default:
panic("unreachable")
}
return req.Presign(expiresIn)
}
```