podman

Форк
0
/
container_commit.go 
178 строк · 5.0 Кб
1
//go:build !remote
2

3
package libpod
4

5
import (
6
	"context"
7
	"errors"
8
	"fmt"
9
	"strings"
10

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"
18
)
19

20
// ContainerCommitOptions is a struct used to commit a container to an image
21
// It uses buildah's CommitOptions as a base. Long-term we might wish to
22
// decouple these because it includes duplicates of fields that are in, or
23
// could later be added, to buildah's CommitOptions, which gets confusing
24
type ContainerCommitOptions struct {
25
	buildah.CommitOptions
26
	Pause          bool
27
	IncludeVolumes bool
28
	Author         string
29
	Message        string
30
	Changes        []string // gets merged with CommitOptions.OverrideChanges
31
	Squash         bool     // always used instead of CommitOptions.Squash
32
}
33

34
// Commit commits the changes between a container and its image, creating a new
35
// image
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")
39
	}
40

41
	if !c.batched {
42
		c.lock.Lock()
43
		defer c.lock.Unlock()
44

45
		if err := c.syncContainer(); err != nil {
46
			return nil, err
47
		}
48
	}
49

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)
53
		}
54
		defer func() {
55
			if err := c.unpause(); err != nil {
56
				logrus.Errorf("Unpausing container %q: %v", c.ID(), err)
57
			}
58
		}()
59
	}
60

61
	builderOptions := buildah.ImportOptions{
62
		Container:           c.ID(),
63
		SignaturePolicyPath: options.SignaturePolicyPath,
64
	}
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,
73
	}
74
	importBuilder, err := buildah.ImportBuilder(ctx, c.runtime.store, builderOptions)
75
	importBuilder.Format = options.PreferredManifestType
76
	if err != nil {
77
		return nil, err
78
	}
79
	if options.Author != "" {
80
		importBuilder.SetMaintainer(options.Author)
81
	}
82
	if options.Message != "" {
83
		importBuilder.SetComment(options.Message)
84
	}
85

86
	// We need to take meta we find in the current container and
87
	// add it to the resulting image.
88

89
	// Entrypoint - always set this first or cmd will get wiped out
90
	importBuilder.SetEntrypoint(c.config.Entrypoint)
91

92
	// Cmd
93
	importBuilder.SetCmd(c.config.Command)
94

95
	// Env
96
	// TODO - this includes all the default environment vars as well
97
	// Should we store the ENV we actually want in the spec separately?
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)
102
		}
103
	}
104
	// Expose ports
105
	for _, p := range c.config.PortMappings {
106
		importBuilder.SetPort(fmt.Sprintf("%d/%s", p.ContainerPort, p.Protocol))
107
	}
108
	for port, protocols := range c.config.ExposedPorts {
109
		for _, protocol := range protocols {
110
			importBuilder.SetPort(fmt.Sprintf("%d/%s", port, protocol))
111
		}
112
	}
113
	// Labels
114
	for k, v := range c.Labels() {
115
		importBuilder.SetLabel(k, v)
116
	}
117
	// No stop signal
118
	// User
119
	if c.config.User != "" {
120
		importBuilder.SetUser(c.config.User)
121
	}
122
	// Volumes
123
	if options.IncludeVolumes {
124
		for _, v := range c.config.UserVolumes {
125
			if v != "" {
126
				importBuilder.AddVolume(v)
127
			}
128
		}
129
	} else {
130
		// Only include anonymous named volumes added by the user by
131
		// default.
132
		for _, v := range c.config.NamedVolumes {
133
			include := false
134
			for _, userVol := range c.config.UserVolumes {
135
				if userVol == v.Dest {
136
					include = true
137
					break
138
				}
139
			}
140
			if include {
141
				vol, err := c.runtime.GetVolume(v.Name)
142
				if err != nil {
143
					return nil, fmt.Errorf("volume %s used in container %s has been removed: %w", v.Name, c.ID(), err)
144
				}
145
				if vol.Anonymous() {
146
					importBuilder.AddVolume(v.Dest)
147
				}
148
			}
149
		}
150
	}
151
	// Workdir
152
	importBuilder.SetWorkDir(c.config.Spec.Process.Cwd)
153

154
	var commitRef types.ImageReference
155
	if destImage != "" {
156
		// Now resolve the name.
157
		resolvedImageName, err := c.runtime.LibimageRuntime().ResolveName(destImage)
158
		if err != nil {
159
			return nil, err
160
		}
161

162
		imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, resolvedImageName)
163
		if err != nil {
164
			return nil, fmt.Errorf("parsing target image name %q: %w", destImage, err)
165
		}
166
		commitRef = imageRef
167
	}
168
	id, _, _, err := importBuilder.Commit(ctx, commitRef, commitOptions)
169
	if err != nil {
170
		return nil, err
171
	}
172
	defer c.newContainerEvent(events.Commit)
173
	img, _, err := c.runtime.libimageRuntime.LookupImage(id, nil)
174
	if err != nil {
175
		return nil, err
176
	}
177
	return img, nil
178
}
179

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.