-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Fix kicbase image load permission denied by using docker CLI #22787
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -31,7 +31,6 @@ import ( | |||||||||||||
| "github.com/cheggaaa/pb/v3" | ||||||||||||||
| "github.com/google/go-containerregistry/pkg/name" | ||||||||||||||
| v1 "github.com/google/go-containerregistry/pkg/v1" | ||||||||||||||
| "github.com/google/go-containerregistry/pkg/v1/daemon" | ||||||||||||||
| "github.com/google/go-containerregistry/pkg/v1/remote" | ||||||||||||||
| "github.com/google/go-containerregistry/pkg/v1/tarball" | ||||||||||||||
| "github.com/hashicorp/go-getter" | ||||||||||||||
|
|
@@ -106,19 +105,15 @@ func ImageExistsInDaemon(img string) bool { | |||||||||||||
| // arch. This is needed to resolve | ||||||||||||||
| // https://github.com/kubernetes/minikube/pull/19205 | ||||||||||||||
| func isImageCorrectArch(img string) (bool, error) { | ||||||||||||||
| ref, err := name.ParseReference(img) | ||||||||||||||
| if err != nil { | ||||||||||||||
| return false, fmt.Errorf("failed to parse reference: %v", err) | ||||||||||||||
| } | ||||||||||||||
| dImg, err := daemon.Image(ref) | ||||||||||||||
| if err != nil { | ||||||||||||||
| return false, fmt.Errorf("failed to get image from daemon: %v", err) | ||||||||||||||
| } | ||||||||||||||
| cfg, err := dImg.ConfigFile() | ||||||||||||||
| // Use the docker CLI instead of directly accessing the Docker daemon | ||||||||||||||
| // socket so that users who access docker via sudo wrappers are supported. | ||||||||||||||
| cmd := exec.Command("docker", "image", "inspect", "--format", "{{.Architecture}}", img) | ||||||||||||||
| output, err := cmd.Output() | ||||||||||||||
| if err != nil { | ||||||||||||||
| return false, fmt.Errorf("failed to get config for %s: %v", img, err) | ||||||||||||||
| return false, fmt.Errorf("failed to inspect image %s: %v", img, err) | ||||||||||||||
| } | ||||||||||||||
| return cfg.Architecture == runtime.GOARCH, nil | ||||||||||||||
| arch := strings.TrimSpace(string(output)) | ||||||||||||||
| return arch == runtime.GOARCH, nil | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| // ImageToCache downloads img (if not present in cache) and writes it to the local cache directory | ||||||||||||||
|
|
@@ -285,30 +280,32 @@ func parseImage(img string) (*name.Tag, name.Reference, error) { | |||||||||||||
| func CacheToDaemon(img string) (string, error) { | ||||||||||||||
| p := imagePathInCache(img) | ||||||||||||||
|
|
||||||||||||||
| tag, ref, err := parseImage(img) | ||||||||||||||
| _, ref, err := parseImage(img) | ||||||||||||||
| if err != nil { | ||||||||||||||
|
Comment on lines
+283
to
284
|
||||||||||||||
| return "", err | ||||||||||||||
| } | ||||||||||||||
| // do not use cache if image is set in format <name>:latest | ||||||||||||||
| if _, ok := ref.(name.Tag); ok { | ||||||||||||||
| if tag.Name() == "latest" { | ||||||||||||||
| if t, ok := ref.(name.Tag); ok { | ||||||||||||||
| if t.TagStr() == "latest" { | ||||||||||||||
| return "", fmt.Errorf("can't cache 'latest' tag") | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| i, err := tarball.ImageFromPath(p, tag) | ||||||||||||||
| // Use the docker CLI to load the image so that users who access docker | ||||||||||||||
| // via sudo wrappers or similar privilege-escalation mechanisms are | ||||||||||||||
| // supported. The previous daemon.Write() call connected directly to | ||||||||||||||
| // the Docker socket, which fails with "permission denied" when the | ||||||||||||||
| // current user doesn't have socket access. | ||||||||||||||
| cmd := exec.Command("docker", "load", "-i", p) | ||||||||||||||
| klog.Infof("Loading image into docker daemon: %v", cmd.Args) | ||||||||||||||
| output, err := cmd.CombinedOutput() | ||||||||||||||
| klog.V(2).Infof("docker load output: %s", output) | ||||||||||||||
| if err != nil { | ||||||||||||||
| return "", fmt.Errorf("tarball: %w", err) | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| resp, err := daemon.Write(*tag, i) | ||||||||||||||
| klog.V(2).Infof("response: %s", resp) | ||||||||||||||
| if err != nil { | ||||||||||||||
| return "", err | ||||||||||||||
| return "", fmt.Errorf("error loading image: %w", err) | ||||||||||||||
|
||||||||||||||
| return "", fmt.Errorf("error loading image: %w", err) | |
| trimmedOutput := strings.TrimSpace(string(output)) | |
| if trimmedOutput != "" { | |
| return "", fmt.Errorf("error loading image with %v: %s: %w", cmd.Args, trimmedOutput, err) | |
| } | |
| return "", fmt.Errorf("error loading image with %v: %w", cmd.Args, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cmd.Output()drops stderr, so failures fromdocker image inspectwill return an unhelpful error (e.g. onlyexit status 1). Consider usingCombinedOutput()and include the captured output in the returned error to make diagnosing inspect failures easier.