Merge pull request #1247 from tonistiigi/dangling-naming
exporter: add canonical and dangling image namingv0.7
commit
e486c1193f
15
README.md
15
README.md
|
@ -45,7 +45,7 @@ You don't need to read this document unless you want to use the full-featured st
|
||||||
- [Building a Dockerfile using external frontend:](#building-a-dockerfile-using-external-frontend)
|
- [Building a Dockerfile using external frontend:](#building-a-dockerfile-using-external-frontend)
|
||||||
- [Building a Dockerfile with experimental features like `RUN --mount=type=(bind|cache|tmpfs|secret|ssh)`](#building-a-dockerfile-with-experimental-features-like-run---mounttypebindcachetmpfssecretssh)
|
- [Building a Dockerfile with experimental features like `RUN --mount=type=(bind|cache|tmpfs|secret|ssh)`](#building-a-dockerfile-with-experimental-features-like-run---mounttypebindcachetmpfssecretssh)
|
||||||
- [Output](#output)
|
- [Output](#output)
|
||||||
- [Registry](#registry)
|
- [Image/Registry](#imageregistry)
|
||||||
- [Local directory](#local-directory)
|
- [Local directory](#local-directory)
|
||||||
- [Docker tarball](#docker-tarball)
|
- [Docker tarball](#docker-tarball)
|
||||||
- [OCI tarball](#oci-tarball)
|
- [OCI tarball](#oci-tarball)
|
||||||
|
@ -199,7 +199,7 @@ See [`frontend/dockerfile/docs/experimental.md`](frontend/dockerfile/docs/experi
|
||||||
|
|
||||||
By default, the build result and intermediate cache will only remain internally in BuildKit. An output needs to be specified to retrieve the result.
|
By default, the build result and intermediate cache will only remain internally in BuildKit. An output needs to be specified to retrieve the result.
|
||||||
|
|
||||||
#### Registry
|
#### Image/Registry
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
buildctl build ... --output type=image,name=docker.io/username/image,push=true
|
buildctl build ... --output type=image,name=docker.io/username/image,push=true
|
||||||
|
@ -215,6 +215,17 @@ buildctl build ...\
|
||||||
--import-cache type=registry,ref=docker.io/username/image
|
--import-cache type=registry,ref=docker.io/username/image
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Keys supported by image output:
|
||||||
|
* `name=[value]`: image name
|
||||||
|
* `push=true`: push after creating the image
|
||||||
|
* `push-by-digest=true`: push unnamed image
|
||||||
|
* `registry.insecure=true`: push to insecure HTTP registry
|
||||||
|
* `oci-mediatypes=true`: use OCI mediatypes in configuration JSON instead of Docker's
|
||||||
|
* `unpack=true`: unpack image after creation (for use with containerd)
|
||||||
|
* `dangling-name-prefix=[value]`: name image with `prefix@<digest>` , used for anonymous images
|
||||||
|
* `name-canonical=true`: add additional canonical name `name@<digest>`
|
||||||
|
|
||||||
|
|
||||||
If credentials are required, `buildctl` will attempt to read Docker configuration file `$DOCKER_CONFIG/config.json`.
|
If credentials are required, `buildctl` will attempt to read Docker configuration file `$DOCKER_CONFIG/config.json`.
|
||||||
`$DOCKER_CONFIG` defaults to `~/.docker`.
|
`$DOCKER_CONFIG` defaults to `~/.docker`.
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ const (
|
||||||
keyPushByDigest = "push-by-digest"
|
keyPushByDigest = "push-by-digest"
|
||||||
keyInsecure = "registry.insecure"
|
keyInsecure = "registry.insecure"
|
||||||
keyUnpack = "unpack"
|
keyUnpack = "unpack"
|
||||||
|
keyDanglingPrefix = "dangling-name-prefix"
|
||||||
|
keyNameCanonical = "name-canonical"
|
||||||
ociTypes = "oci-mediatypes"
|
ociTypes = "oci-mediatypes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -111,6 +113,18 @@ func (e *imageExporter) Resolve(ctx context.Context, opt map[string]string) (exp
|
||||||
return nil, errors.Wrapf(err, "non-bool value specified for %s", k)
|
return nil, errors.Wrapf(err, "non-bool value specified for %s", k)
|
||||||
}
|
}
|
||||||
i.ociTypes = b
|
i.ociTypes = b
|
||||||
|
case keyDanglingPrefix:
|
||||||
|
i.danglingPrefix = v
|
||||||
|
case keyNameCanonical:
|
||||||
|
if v == "" {
|
||||||
|
i.nameCanonical = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b, err := strconv.ParseBool(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "non-bool value specified for %s", k)
|
||||||
|
}
|
||||||
|
i.nameCanonical = b
|
||||||
default:
|
default:
|
||||||
if i.meta == nil {
|
if i.meta == nil {
|
||||||
i.meta = make(map[string][]byte)
|
i.meta = make(map[string][]byte)
|
||||||
|
@ -129,6 +143,8 @@ type imageExporterInstance struct {
|
||||||
unpack bool
|
unpack bool
|
||||||
insecure bool
|
insecure bool
|
||||||
ociTypes bool
|
ociTypes bool
|
||||||
|
nameCanonical bool
|
||||||
|
danglingPrefix string
|
||||||
meta map[string][]byte
|
meta map[string][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,17 +181,27 @@ func (e *imageExporterInstance) Export(ctx context.Context, src exporter.Source)
|
||||||
e.targetName = string(n)
|
e.targetName = string(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nameCanonical := e.nameCanonical
|
||||||
|
if e.targetName == "" && e.danglingPrefix != "" {
|
||||||
|
e.targetName = e.danglingPrefix + "@" + desc.Digest.String()
|
||||||
|
nameCanonical = false
|
||||||
|
}
|
||||||
|
|
||||||
if e.targetName != "" {
|
if e.targetName != "" {
|
||||||
targetNames := strings.Split(e.targetName, ",")
|
targetNames := strings.Split(e.targetName, ",")
|
||||||
for _, targetName := range targetNames {
|
for _, targetName := range targetNames {
|
||||||
if e.opt.Images != nil {
|
if e.opt.Images != nil {
|
||||||
tagDone := oneOffProgress(ctx, "naming to "+targetName)
|
tagDone := oneOffProgress(ctx, "naming to "+targetName)
|
||||||
img := images.Image{
|
img := images.Image{
|
||||||
Name: targetName,
|
|
||||||
Target: *desc,
|
Target: *desc,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
}
|
}
|
||||||
|
sfx := []string{""}
|
||||||
|
if nameCanonical {
|
||||||
|
sfx = append(sfx, "@"+desc.Digest.String())
|
||||||
|
}
|
||||||
|
for _, sfx := range sfx {
|
||||||
|
img.Name = targetName + sfx
|
||||||
if _, err := e.opt.Images.Update(ctx, img); err != nil {
|
if _, err := e.opt.Images.Update(ctx, img); err != nil {
|
||||||
if !errdefs.IsNotFound(err) {
|
if !errdefs.IsNotFound(err) {
|
||||||
return nil, tagDone(err)
|
return nil, tagDone(err)
|
||||||
|
@ -185,6 +211,7 @@ func (e *imageExporterInstance) Export(ctx context.Context, src exporter.Source)
|
||||||
return nil, tagDone(err)
|
return nil, tagDone(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
tagDone(nil)
|
tagDone(nil)
|
||||||
|
|
||||||
if e.unpack {
|
if e.unpack {
|
||||||
|
|
Loading…
Reference in New Issue