11
"github.com/containers/buildah"
12
"github.com/containers/common/libimage"
13
is "github.com/containers/image/v5/storage"
14
"github.com/containers/image/v5/types"
15
"github.com/containers/podman/v5/libpod/define"
16
"github.com/containers/podman/v5/libpod/events"
17
"github.com/sirupsen/logrus"
24
type ContainerCommitOptions struct {
36
func (c *Container) Commit(ctx context.Context, destImage string, options ContainerCommitOptions) (*libimage.Image, error) {
37
if c.config.Rootfs != "" {
38
return nil, errors.New("cannot commit a container that uses an exploded rootfs")
45
if err := c.syncContainer(); err != nil {
50
if c.state.State == define.ContainerStateRunning && options.Pause {
51
if err := c.pause(); err != nil {
52
return nil, fmt.Errorf("pausing container %q to commit: %w", c.ID(), err)
55
if err := c.unpause(); err != nil {
56
logrus.Errorf("Unpausing container %q: %v", c.ID(), err)
61
builderOptions := buildah.ImportOptions{
63
SignaturePolicyPath: options.SignaturePolicyPath,
65
commitOptions := buildah.CommitOptions{
66
SignaturePolicyPath: options.SignaturePolicyPath,
67
ReportWriter: options.ReportWriter,
68
Squash: options.Squash,
69
SystemContext: c.runtime.imageContext,
70
PreferredManifestType: options.PreferredManifestType,
71
OverrideChanges: append(append([]string{}, options.Changes...), options.CommitOptions.OverrideChanges...),
72
OverrideConfig: options.CommitOptions.OverrideConfig,
74
importBuilder, err := buildah.ImportBuilder(ctx, c.runtime.store, builderOptions)
75
importBuilder.Format = options.PreferredManifestType
79
if options.Author != "" {
80
importBuilder.SetMaintainer(options.Author)
82
if options.Message != "" {
83
importBuilder.SetComment(options.Message)
90
importBuilder.SetEntrypoint(c.config.Entrypoint)
93
importBuilder.SetCmd(c.config.Command)
98
if c.config.Spec.Process != nil {
99
for _, e := range c.config.Spec.Process.Env {
100
key, val, _ := strings.Cut(e, "=")
101
importBuilder.SetEnv(key, val)
105
for _, p := range c.config.PortMappings {
106
importBuilder.SetPort(fmt.Sprintf("%d/%s", p.ContainerPort, p.Protocol))
108
for port, protocols := range c.config.ExposedPorts {
109
for _, protocol := range protocols {
110
importBuilder.SetPort(fmt.Sprintf("%d/%s", port, protocol))
114
for k, v := range c.Labels() {
115
importBuilder.SetLabel(k, v)
119
if c.config.User != "" {
120
importBuilder.SetUser(c.config.User)
123
if options.IncludeVolumes {
124
for _, v := range c.config.UserVolumes {
126
importBuilder.AddVolume(v)
132
for _, v := range c.config.NamedVolumes {
134
for _, userVol := range c.config.UserVolumes {
135
if userVol == v.Dest {
141
vol, err := c.runtime.GetVolume(v.Name)
143
return nil, fmt.Errorf("volume %s used in container %s has been removed: %w", v.Name, c.ID(), err)
146
importBuilder.AddVolume(v.Dest)
152
importBuilder.SetWorkDir(c.config.Spec.Process.Cwd)
154
var commitRef types.ImageReference
157
resolvedImageName, err := c.runtime.LibimageRuntime().ResolveName(destImage)
162
imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, resolvedImageName)
164
return nil, fmt.Errorf("parsing target image name %q: %w", destImage, err)
168
id, _, _, err := importBuilder.Commit(ctx, commitRef, commitOptions)
172
defer c.newContainerEvent(events.Commit)
173
img, _, err := c.runtime.libimageRuntime.LookupImage(id, nil)