1
0
mirror of https://github.com/containers/buildah.git synced 2025-08-09 10:22:49 +03:00
Files
buildah/cmd/buildah/commit.go
Nalin Dahyabhai c806e6e065 Implement --squash for build-using-dockerfile and commit
Handle a Squash option when committing images, and make it available as
a flag for "buildah commit" and "buildah build-using-dockerfile".

Breaks up containerImageRef.NewImageSource to keep the complexity more
manageable.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>

Closes: #714
Approved by: rhatdan
2018-05-22 16:43:58 +00:00

184 lines
4.8 KiB
Go

package main
import (
"fmt"
"os"
"strings"
"time"
"github.com/containers/image/storage"
"github.com/containers/image/transports/alltransports"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/projectatomic/buildah"
"github.com/projectatomic/buildah/pkg/parse"
"github.com/projectatomic/buildah/util"
"github.com/urfave/cli"
)
var (
commitFlags = []cli.Flag{
cli.StringFlag{
Name: "authfile",
Usage: "path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json",
},
cli.StringFlag{
Name: "cert-dir",
Value: "",
Usage: "use certificates at the specified path to access the registry",
},
cli.StringFlag{
Name: "creds",
Value: "",
Usage: "use `[username[:password]]` for accessing the registry",
},
cli.BoolFlag{
Name: "disable-compression, D",
Usage: "don't compress layers",
},
cli.StringFlag{
Name: "format, f",
Usage: "`format` of the image manifest and metadata",
Value: "oci",
},
cli.StringFlag{
Name: "iidfile",
Usage: "Write the image ID to the file",
},
cli.BoolFlag{
Name: "quiet, q",
Usage: "don't output progress information when writing images",
},
cli.StringFlag{
Name: "reference-time",
Usage: "set the timestamp on the image to match the named `file`",
Hidden: true,
},
cli.BoolFlag{
Name: "rm",
Usage: "remove the container and its content after committing it to an image. Default leaves the container and its content in place.",
},
cli.StringFlag{
Name: "signature-policy",
Usage: "`pathname` of signature policy file (not usually used)",
},
cli.BoolFlag{
Name: "squash",
Usage: "produce an image with only one layer",
},
cli.BoolTFlag{
Name: "tls-verify",
Usage: "Require HTTPS and verify certificates when accessing the registry",
},
}
commitDescription = "Writes a new image using the container's read-write layer and, if it is based\n on an image, the layers of that image"
commitCommand = cli.Command{
Name: "commit",
Usage: "Create an image from a working container",
Description: commitDescription,
Flags: commitFlags,
Action: commitCmd,
ArgsUsage: "CONTAINER-NAME-OR-ID IMAGE",
SkipArgReorder: true,
}
)
func commitCmd(c *cli.Context) error {
args := c.Args()
if len(args) == 0 {
return errors.Errorf("container ID must be specified")
}
name := args[0]
args = args.Tail()
if len(args) == 0 {
return errors.Errorf("an image name must be specified")
}
if len(args) > 1 {
return errors.Errorf("too many arguments specified")
}
image := args[0]
if err := parse.ValidateFlags(c, commitFlags); err != nil {
return err
}
compress := archive.Gzip
if c.Bool("disable-compression") {
compress = archive.Uncompressed
}
timestamp := time.Now().UTC()
if c.IsSet("reference-time") {
referenceFile := c.String("reference-time")
finfo, err := os.Stat(referenceFile)
if err != nil {
return errors.Wrapf(err, "error reading timestamp of file %q", referenceFile)
}
timestamp = finfo.ModTime().UTC()
}
format := c.String("format")
if strings.HasPrefix(strings.ToLower(format), "oci") {
format = buildah.OCIv1ImageManifest
} else if strings.HasPrefix(strings.ToLower(format), "docker") {
format = buildah.Dockerv2ImageManifest
} else {
return errors.Errorf("unrecognized image type %q", format)
}
store, err := getStore(c)
if err != nil {
return err
}
ctx := getContext()
builder, err := openBuilder(ctx, store, name)
if err != nil {
return errors.Wrapf(err, "error reading build container %q", name)
}
systemContext, err := parse.SystemContextFromOptions(c)
if err != nil {
return errors.Wrapf(err, "error building system context")
}
dest, err := alltransports.ParseImageName(image)
if err != nil {
candidates := util.ResolveName(image, "", systemContext, store)
if len(candidates) == 0 {
return errors.Errorf("error parsing target image name %q", image)
}
dest2, err2 := storage.Transport.ParseStoreReference(store, candidates[0])
if err2 != nil {
return errors.Wrapf(err, "error parsing target image name %q", image)
}
dest = dest2
}
options := buildah.CommitOptions{
PreferredManifestType: format,
Compression: compress,
SignaturePolicyPath: c.String("signature-policy"),
HistoryTimestamp: &timestamp,
SystemContext: systemContext,
IIDFile: c.String("iidfile"),
Squash: c.Bool("squash"),
}
if !c.Bool("quiet") {
options.ReportWriter = os.Stderr
}
id, err := builder.Commit(ctx, dest, options)
if err != nil {
return util.GetFailureCause(
err,
errors.Wrapf(err, "error committing container %q to %q", builder.Container, image),
)
}
if options.IIDFile == "" && id != "" {
fmt.Printf("%s\n", id)
}
if c.Bool("rm") {
return builder.Delete()
}
return nil
}