Skip to content

Commit 60464b6

Browse files
committed
optimize memory usage in image load with Docker client integration
Signed-off-by: Kay Yan <[email protected]>
1 parent 6ff37d5 commit 60464b6

File tree

2 files changed

+54
-5
lines changed

2 files changed

+54
-5
lines changed

pkg/minikube/image/cache.go

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ limitations under the License.
1717
package image
1818

1919
import (
20+
"context"
21+
"io"
2022
"os"
2123
"path/filepath"
2224
"time"
2325

26+
"github.com/docker/docker/client"
2427
"github.com/google/go-containerregistry/pkg/name"
2528
v1 "github.com/google/go-containerregistry/pkg/v1"
2629
"github.com/google/go-containerregistry/pkg/v1/tarball"
@@ -84,7 +87,6 @@ func SaveToDir(images []string, cacheDir string, overwrite bool) error {
8487
if err := g.Wait(); err != nil {
8588
return errors.Wrap(err, "caching images")
8689
}
87-
klog.Infoln("Successfully saved all images to host disk.")
8890
return nil
8991
}
9092

@@ -158,6 +160,36 @@ func saveToTarFile(iname, rawDest string, overwrite bool) error {
158160
return nil
159161
}
160162

163+
func saveImageWithDockerClient(f *os.File, ref name.Reference) error {
164+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
165+
if err != nil {
166+
return errors.Wrap(err, "creating docker client")
167+
}
168+
defer cli.Close()
169+
170+
ctx := context.Background()
171+
172+
_, _, err = cli.ImageInspectWithRaw(ctx, ref.String())
173+
if err != nil {
174+
return errors.Wrapf(err, "inspect image %s via docker client", ref.String())
175+
}
176+
177+
imageResponse, err := cli.ImageSave(ctx, []string{ref.String()})
178+
if err != nil {
179+
return errors.Wrapf(err, "saving image %s via docker client", ref.String())
180+
}
181+
defer imageResponse.Close()
182+
183+
// Copy image data stream to file
184+
_, err = io.Copy(f, imageResponse)
185+
if err != nil {
186+
return errors.Wrapf(err, "copying image %s data to file", ref.String())
187+
}
188+
189+
klog.Infof("Successfully saved image %s using Docker client", ref.String())
190+
return nil
191+
}
192+
161193
func writeImage(img v1.Image, dst string, ref name.Reference) error {
162194
klog.Infoln("opening: ", dst)
163195
f, err := os.CreateTemp(filepath.Dir(dst), filepath.Base(dst)+".*.tmp")
@@ -175,10 +207,27 @@ func writeImage(img v1.Image, dst string, ref name.Reference) error {
175207
}
176208
}()
177209

178-
err = tarball.Write(ref, img, f)
179-
if err != nil {
180-
return errors.Wrap(err, "write")
210+
var imageSaved bool
211+
212+
// Using the Docker client to save the image for better performance
213+
if useDaemon {
214+
// Try to save the image using the Docker client
215+
if err := saveImageWithDockerClient(f, ref); err != nil {
216+
if !client.IsErrNotFound(err) {
217+
return errors.Wrap(err, "docker save")
218+
}
219+
klog.Warningf("Failed to save image with Docker client: %v, falling back to tarball.Write", err)
220+
} else {
221+
imageSaved = true
222+
}
181223
}
224+
// Fallback to saving the image using the tarball package
225+
if !imageSaved {
226+
if err := tarball.Write(ref, img, f); err != nil {
227+
return errors.Wrap(err, "write")
228+
}
229+
}
230+
182231
err = f.Close()
183232
if err != nil {
184233
return errors.Wrap(err, "close")

pkg/minikube/image/image.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ func retrieveImage(ref name.Reference, imgName string) (v1.Image, string, error)
169169
}
170170

171171
func retrieveDaemon(ref name.Reference) (v1.Image, error) {
172-
img, err := daemon.Image(ref)
172+
img, err := daemon.Image(ref) // uses bufferedOpener, which may consume a significant amount of memory
173173
if err == nil {
174174
klog.Infof("found %s locally: %+v", ref.Name(), img)
175175
return img, nil

0 commit comments

Comments
 (0)