1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
package libpod
import (
"context"
"strings"
is "github.com/containers/image/storage"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod/buildah"
"github.com/projectatomic/libpod/libpod/image"
"github.com/sirupsen/logrus"
)
// ContainerCommitOptions is a struct used to commit a container to an image
// It uses buildah's CommitOptions as a base. Long-term we might wish to
// add these to the buildah struct once buildah is more integrated with
//libpod
type ContainerCommitOptions struct {
buildah.CommitOptions
Pause bool
Author string
Message string
Changes []string
}
// Commit commits the changes between a container and its image, creating a new
// image
func (c *Container) Commit(ctx context.Context, destImage string, options ContainerCommitOptions) (*image.Image, error) {
if !c.batched {
c.lock.Lock()
defer c.lock.Unlock()
if err := c.syncContainer(); err != nil {
return nil, err
}
}
if c.state.State == ContainerStateRunning && options.Pause {
if err := c.runtime.ociRuntime.pauseContainer(c); err != nil {
return nil, errors.Wrapf(err, "error pausing container %q", c.ID())
}
defer func() {
if err := c.runtime.ociRuntime.unpauseContainer(c); err != nil {
logrus.Errorf("error unpausing container %q: %v", c.ID(), err)
}
}()
}
sc := image.GetSystemContext(options.SignaturePolicyPath, "", false)
builderOptions := buildah.ImportOptions{
Container: c.ID(),
SignaturePolicyPath: options.SignaturePolicyPath,
}
commitOptions := buildah.CommitOptions{
SignaturePolicyPath: options.SignaturePolicyPath,
ReportWriter: options.ReportWriter,
SystemContext: sc,
}
importBuilder, err := buildah.ImportBuilder(ctx, c.runtime.store, builderOptions)
if err != nil {
return nil, err
}
if options.Author != "" {
importBuilder.SetMaintainer(options.Author)
}
if options.Message != "" {
importBuilder.SetComment(options.Message)
}
// Process user changes
for _, change := range options.Changes {
splitChange := strings.Split(change, "=")
switch strings.ToUpper(splitChange[0]) {
case "CMD":
importBuilder.SetCmd(splitChange[1:])
case "ENTRYPOINT":
importBuilder.SetEntrypoint(splitChange[1:])
case "ENV":
importBuilder.SetEnv(splitChange[1], splitChange[2])
case "EXPOSE":
importBuilder.SetPort(splitChange[1])
case "LABEL":
importBuilder.SetLabel(splitChange[1], splitChange[2])
case "STOPSIGNAL":
// No Set StopSignal
case "USER":
importBuilder.SetUser(splitChange[1])
case "VOLUME":
importBuilder.AddVolume(splitChange[1])
case "WORKDIR":
importBuilder.SetWorkDir(splitChange[1])
}
}
imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, destImage)
if err != nil {
return nil, err
}
if err = importBuilder.Commit(ctx, imageRef, commitOptions); err != nil {
return nil, err
}
return c.runtime.imageRuntime.NewFromLocal(imageRef.DockerReference().String())
}
|