f95f5828 |
package dockerfile
import ( |
a97817b6 |
"runtime"
|
6c28e8ed |
"github.com/docker/docker/api/types/backend" |
f95f5828 |
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/remotecontext" |
51360965 |
dockerimage "github.com/docker/docker/image" |
d98ecf2d |
"github.com/docker/docker/pkg/system" |
f95f5828 |
"github.com/pkg/errors" |
1009e6a4 |
"github.com/sirupsen/logrus" |
6c28e8ed |
"golang.org/x/net/context" |
f95f5828 |
)
|
c268d9da |
type getAndMountFunc func(string, bool) (builder.Image, builder.ReleaseableLayer, error) |
6c28e8ed |
// imageSources mounts images and provides a cache for mounted images. It tracks
// all images so they can be unmounted at the end of the build.
type imageSources struct {
byImageID map[string]*imageMount |
c268d9da |
mounts []*imageMount |
6c28e8ed |
getImage getAndMountFunc
}
func newImageSources(ctx context.Context, options builderOptions) *imageSources { |
c268d9da |
getAndMount := func(idOrRef string, localOnly bool) (builder.Image, builder.ReleaseableLayer, error) {
pullOption := backend.PullOptionNoPull
if !localOnly {
if options.Options.PullParent {
pullOption = backend.PullOptionForcePull
} else {
pullOption = backend.PullOptionPreferLocal
}
} |
d98ecf2d |
optionsPlatform := system.ParsePlatform(options.Options.Platform) |
6c28e8ed |
return options.Backend.GetImageAndReleasableLayer(ctx, idOrRef, backend.GetImageAndLayerOptions{ |
c268d9da |
PullOption: pullOption, |
6c28e8ed |
AuthConfig: options.Options.AuthConfigs,
Output: options.ProgressWriter.Output, |
d98ecf2d |
OS: optionsPlatform.OS, |
6c28e8ed |
})
}
return &imageSources{
byImageID: make(map[string]*imageMount),
getImage: getAndMount,
}
}
|
c268d9da |
func (m *imageSources) Get(idOrRef string, localOnly bool) (*imageMount, error) { |
6c28e8ed |
if im, ok := m.byImageID[idOrRef]; ok {
return im, nil
}
|
c268d9da |
image, layer, err := m.getImage(idOrRef, localOnly) |
6c28e8ed |
if err != nil {
return nil, err
}
im := newImageMount(image, layer) |
51360965 |
m.Add(im) |
6c28e8ed |
return im, nil
}
func (m *imageSources) Unmount() (retErr error) { |
c268d9da |
for _, im := range m.mounts { |
51360965 |
if err := im.unmount(); err != nil {
logrus.Error(err)
retErr = err
}
} |
f95f5828 |
return
}
|
51360965 |
func (m *imageSources) Add(im *imageMount) {
switch im.image {
case nil: |
a97817b6 |
// set the OS for scratch images
os := runtime.GOOS
// Windows does not support scratch except for LCOW
if runtime.GOOS == "windows" {
os = "linux"
}
im.image = &dockerimage.Image{V1Image: dockerimage.V1Image{OS: os}} |
51360965 |
default:
m.byImageID[im.image.ImageID()] = im
} |
c268d9da |
m.mounts = append(m.mounts, im) |
51360965 |
}
|
b3bc7b28 |
// imageMount is a reference to an image that can be used as a builder.Source |
73b4b8ed |
type imageMount struct { |
6c28e8ed |
image builder.Image
source builder.Source
layer builder.ReleaseableLayer |
b3bc7b28 |
}
func newImageMount(image builder.Image, layer builder.ReleaseableLayer) *imageMount { |
6c28e8ed |
im := &imageMount{image: image, layer: layer} |
b3bc7b28 |
return im |
73b4b8ed |
}
|
6c28e8ed |
func (im *imageMount) Source() (builder.Source, error) { |
d1faf3df |
if im.source == nil { |
6c28e8ed |
if im.layer == nil { |
b3bc7b28 |
return nil, errors.Errorf("empty context") |
73b4b8ed |
} |
6c28e8ed |
mountPath, err := im.layer.Mount() |
73b4b8ed |
if err != nil { |
6c28e8ed |
return nil, errors.Wrapf(err, "failed to mount %s", im.image.ImageID()) |
73b4b8ed |
} |
ecd44d23 |
source, err := remotecontext.NewLazySource(mountPath) |
73b4b8ed |
if err != nil { |
b3bc7b28 |
return nil, errors.Wrapf(err, "failed to create lazycontext for %s", mountPath) |
73b4b8ed |
} |
d1faf3df |
im.source = source |
73b4b8ed |
} |
d1faf3df |
return im.source, nil |
73b4b8ed |
}
func (im *imageMount) unmount() error { |
ab3a037a |
if im.layer == nil {
return nil
} |
b3bc7b28 |
if err := im.layer.Release(); err != nil { |
6c28e8ed |
return errors.Wrapf(err, "failed to unmount previous build image %s", im.image.ImageID()) |
73b4b8ed |
} |
51360965 |
im.layer = nil |
73b4b8ed |
return nil
}
|
6c28e8ed |
func (im *imageMount) Image() builder.Image {
return im.image |
672ea30a |
} |
213ed02e |
|
51360965 |
func (im *imageMount) Layer() builder.ReleaseableLayer {
return im.layer |
213ed02e |
} |
bd5f92d2 |
|
51360965 |
func (im *imageMount) ImageID() string {
return im.image.ImageID() |
bd5f92d2 |
} |