mirror of https://github.com/containers/podman.git
container-commit: support --squash to squash layers into one
Allow users to commit containers into a single layer. Usage ```bash podman container commit --squash <name> ``` Signed-off-by: Aditya R <arajan@redhat.com>
This commit is contained in:
parent
0cfb5d7e75
commit
fbbcb957c7
|
@ -77,6 +77,7 @@ func commitFlags(cmd *cobra.Command) {
|
||||||
|
|
||||||
flags.BoolVarP(&commitOptions.Pause, "pause", "p", false, "Pause container during commit")
|
flags.BoolVarP(&commitOptions.Pause, "pause", "p", false, "Pause container during commit")
|
||||||
flags.BoolVarP(&commitOptions.Quiet, "quiet", "q", false, "Suppress output")
|
flags.BoolVarP(&commitOptions.Quiet, "quiet", "q", false, "Suppress output")
|
||||||
|
flags.BoolVarP(&commitOptions.Squash, "squash", "s", false, "squash newly built layers into a single new layer")
|
||||||
flags.BoolVar(&commitOptions.IncludeVolumes, "include-volumes", false, "Include container volumes as image volumes")
|
flags.BoolVar(&commitOptions.IncludeVolumes, "include-volumes", false, "Include container volumes as image volumes")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,11 @@ Set commit message for committed image.\
|
||||||
Pause the container when creating an image.\
|
Pause the container when creating an image.\
|
||||||
The default is **false**.
|
The default is **false**.
|
||||||
|
|
||||||
|
#### **--squash**, **-s**
|
||||||
|
|
||||||
|
Squash newly built layers into a single new layer.\
|
||||||
|
The default is **false**.
|
||||||
|
|
||||||
#### **--quiet**, **-q**
|
#### **--quiet**, **-q**
|
||||||
|
|
||||||
Suppresses output.\
|
Suppresses output.\
|
||||||
|
|
|
@ -27,6 +27,7 @@ type ContainerCommitOptions struct {
|
||||||
Author string
|
Author string
|
||||||
Message string
|
Message string
|
||||||
Changes []string
|
Changes []string
|
||||||
|
Squash bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit commits the changes between a container and its image, creating a new
|
// Commit commits the changes between a container and its image, creating a new
|
||||||
|
@ -63,6 +64,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
|
||||||
commitOptions := buildah.CommitOptions{
|
commitOptions := buildah.CommitOptions{
|
||||||
SignaturePolicyPath: options.SignaturePolicyPath,
|
SignaturePolicyPath: options.SignaturePolicyPath,
|
||||||
ReportWriter: options.ReportWriter,
|
ReportWriter: options.ReportWriter,
|
||||||
|
Squash: options.Squash,
|
||||||
SystemContext: c.runtime.imageContext,
|
SystemContext: c.runtime.imageContext,
|
||||||
PreferredManifestType: options.PreferredManifestType,
|
PreferredManifestType: options.PreferredManifestType,
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
Comment string `schema:"comment"`
|
Comment string `schema:"comment"`
|
||||||
Container string `schema:"container"`
|
Container string `schema:"container"`
|
||||||
Pause bool `schema:"pause"`
|
Pause bool `schema:"pause"`
|
||||||
|
Squash bool `schema:"squash"`
|
||||||
Repo string `schema:"repo"`
|
Repo string `schema:"repo"`
|
||||||
Tag string `schema:"tag"`
|
Tag string `schema:"tag"`
|
||||||
// fromSrc string # fromSrc is currently unused
|
// fromSrc string # fromSrc is currently unused
|
||||||
|
@ -138,6 +139,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
options.Message = query.Comment
|
options.Message = query.Comment
|
||||||
options.Author = query.Author
|
options.Author = query.Author
|
||||||
options.Pause = query.Pause
|
options.Pause = query.Pause
|
||||||
|
options.Squash = query.Squash
|
||||||
for _, change := range query.Changes {
|
for _, change := range query.Changes {
|
||||||
options.Changes = append(options.Changes, strings.Split(change, "\n")...)
|
options.Changes = append(options.Changes, strings.Split(change, "\n")...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -497,6 +497,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
Container string `schema:"container"`
|
Container string `schema:"container"`
|
||||||
Format string `schema:"format"`
|
Format string `schema:"format"`
|
||||||
Pause bool `schema:"pause"`
|
Pause bool `schema:"pause"`
|
||||||
|
Squash bool `schema:"squash"`
|
||||||
Repo string `schema:"repo"`
|
Repo string `schema:"repo"`
|
||||||
Tag string `schema:"tag"`
|
Tag string `schema:"tag"`
|
||||||
}{
|
}{
|
||||||
|
@ -543,6 +544,7 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
options.Message = query.Comment
|
options.Message = query.Comment
|
||||||
options.Author = query.Author
|
options.Author = query.Author
|
||||||
options.Pause = query.Pause
|
options.Pause = query.Pause
|
||||||
|
options.Squash = query.Squash
|
||||||
options.Changes = query.Changes
|
options.Changes = query.Changes
|
||||||
ctr, err := runtime.LookupContainer(query.Container)
|
ctr, err := runtime.LookupContainer(query.Container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -460,6 +460,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||||
// name: changes
|
// name: changes
|
||||||
// type: string
|
// type: string
|
||||||
// description: instructions to apply while committing in Dockerfile format
|
// description: instructions to apply while committing in Dockerfile format
|
||||||
|
// - in: query
|
||||||
|
// name: squash
|
||||||
|
// type: boolean
|
||||||
|
// description: squash newly built layers into a single new layer
|
||||||
// produces:
|
// produces:
|
||||||
// - application/json
|
// - application/json
|
||||||
// responses:
|
// responses:
|
||||||
|
|
|
@ -30,6 +30,7 @@ type CommitOptions struct {
|
||||||
Comment *string
|
Comment *string
|
||||||
Format *string
|
Format *string
|
||||||
Pause *bool
|
Pause *bool
|
||||||
|
Squash *bool
|
||||||
Repo *string
|
Repo *string
|
||||||
Tag *string
|
Tag *string
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,6 +92,21 @@ func (o *CommitOptions) GetPause() bool {
|
||||||
return *o.Pause
|
return *o.Pause
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithSquash set field Squash to given value
|
||||||
|
func (o *CommitOptions) WithSquash(value bool) *CommitOptions {
|
||||||
|
o.Squash = &value
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSquash returns value of field Squash
|
||||||
|
func (o *CommitOptions) GetSquash() bool {
|
||||||
|
if o.Squash == nil {
|
||||||
|
var z bool
|
||||||
|
return z
|
||||||
|
}
|
||||||
|
return *o.Squash
|
||||||
|
}
|
||||||
|
|
||||||
// WithRepo set field Repo to given value
|
// WithRepo set field Repo to given value
|
||||||
func (o *CommitOptions) WithRepo(value string) *CommitOptions {
|
func (o *CommitOptions) WithRepo(value string) *CommitOptions {
|
||||||
o.Repo = &value
|
o.Repo = &value
|
||||||
|
|
|
@ -154,6 +154,7 @@ type CommitOptions struct {
|
||||||
Message string
|
Message string
|
||||||
Pause bool
|
Pause bool
|
||||||
Quiet bool
|
Quiet bool
|
||||||
|
Squash bool
|
||||||
Writer io.Writer
|
Writer io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -528,6 +528,7 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string,
|
||||||
Message: options.Message,
|
Message: options.Message,
|
||||||
Changes: options.Changes,
|
Changes: options.Changes,
|
||||||
Author: options.Author,
|
Author: options.Author,
|
||||||
|
Squash: options.Squash,
|
||||||
}
|
}
|
||||||
newImage, err := ctr.Commit(ctx, options.ImageName, opts)
|
newImage, err := ctr.Commit(ctx, options.ImageName, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -302,7 +302,7 @@ func (ic *ContainerEngine) ContainerCommit(ctx context.Context, nameOrID string,
|
||||||
return nil, errors.Errorf("invalid image name %q", opts.ImageName)
|
return nil, errors.Errorf("invalid image name %q", opts.ImageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
options := new(containers.CommitOptions).WithAuthor(opts.Author).WithChanges(opts.Changes).WithComment(opts.Message)
|
options := new(containers.CommitOptions).WithAuthor(opts.Author).WithChanges(opts.Changes).WithComment(opts.Message).WithSquash(opts.Squash)
|
||||||
options.WithFormat(opts.Format).WithPause(opts.Pause).WithRepo(repo).WithTag(tag)
|
options.WithFormat(opts.Format).WithPause(opts.Pause).WithRepo(repo).WithTag(tag)
|
||||||
response, err := containers.Commit(ic.ClientCtx, nameOrID, options)
|
response, err := containers.Commit(ic.ClientCtx, nameOrID, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/containers/podman/v4/test/utils"
|
. "github.com/containers/podman/v4/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
|
@ -133,6 +134,23 @@ var _ = Describe("Podman commit", func() {
|
||||||
Expect(foundBlue).To(Equal(true))
|
Expect(foundBlue).To(Equal(true))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman commit container with --squash", func() {
|
||||||
|
test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
|
||||||
|
test.WaitWithDefaultTimeout()
|
||||||
|
Expect(test).Should(Exit(0))
|
||||||
|
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
|
||||||
|
|
||||||
|
session := podmanTest.Podman([]string{"commit", "--squash", "test1", "foobar.com/test1-image:latest"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
|
||||||
|
session = podmanTest.Podman([]string{"inspect", "--format", "{{.RootFS.Layers}}", "foobar.com/test1-image:latest"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session).Should(Exit(0))
|
||||||
|
// Check for one layers
|
||||||
|
Expect(strings.Fields(session.OutputToString())).To(HaveLen(1))
|
||||||
|
})
|
||||||
|
|
||||||
It("podman commit container with change flag and JSON entrypoint with =", func() {
|
It("podman commit container with change flag and JSON entrypoint with =", func() {
|
||||||
test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
|
test := podmanTest.Podman([]string{"run", "--name", "test1", "-d", ALPINE, "ls"})
|
||||||
test.WaitWithDefaultTimeout()
|
test.WaitWithDefaultTimeout()
|
||||||
|
|
Loading…
Reference in New Issue