mirror of
https://github.com/containers/skopeo.git
synced 2025-08-20 23:43:22 +00:00
Work around Docker Desktop's macOS socket location change
Docker Desktop 4.13.0+ moved the socket from /var/run/docker.sock to ~/.docker/run/docker.sock on macOS, but the Docker client library still defaults to the old location for all Unix systems. Add platform-specific logic to use the correct default on macOS when --daemon-host is not specified. This makes skopeo work more reliable out of the box for new users. Signed-off-by: Jacques Nadeau <jacques@apache.org>
This commit is contained in:
parent
729a053464
commit
8ec3080e14
@ -6,6 +6,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -32,7 +34,20 @@ import (
|
||||
"golang.org/x/term"
|
||||
)
|
||||
|
||||
// errorShouldDisplayUsage is a subtype of error used by command handlers to indicate that the command’s help should be included.
|
||||
// getDefaultDockerSocket returns the platform-specific default Docker socket path
|
||||
func getDefaultDockerSocket() string {
|
||||
if runtime.GOOS == "darwin" {
|
||||
// On macOS, use the user-specific Docker socket location
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
return "unix://" + filepath.Join(home, ".docker/run/docker.sock")
|
||||
}
|
||||
}
|
||||
// For all other platforms or if HOME is not set, return empty string
|
||||
// to use the default from the Docker client library
|
||||
return ""
|
||||
}
|
||||
|
||||
// errorShouldDisplayUsage is a subtype of error used by command handlers to indicate that the command's help should be included.
|
||||
type errorShouldDisplayUsage struct {
|
||||
error
|
||||
}
|
||||
@ -204,6 +219,12 @@ func (opts *imageOptions) newSystemContext() (*types.SystemContext, error) {
|
||||
ctx.OCISharedBlobDirPath = opts.sharedBlobDir
|
||||
ctx.AuthFilePath = opts.shared.authFilePath
|
||||
ctx.DockerDaemonHost = opts.dockerDaemonHost
|
||||
// Set platform-specific default for Docker daemon host if not explicitly set
|
||||
if ctx.DockerDaemonHost == "" {
|
||||
if defaultSocket := getDefaultDockerSocket(); defaultSocket != "" {
|
||||
ctx.DockerDaemonHost = defaultSocket
|
||||
}
|
||||
}
|
||||
ctx.DockerDaemonCertPath = opts.dockerCertPath
|
||||
if opts.authFilePath.Present() {
|
||||
ctx.AuthFilePath = opts.authFilePath.Value()
|
||||
|
33
cmd/skopeo/utils_darwin_test.go
Normal file
33
cmd/skopeo/utils_darwin_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
//go:build darwin
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetDefaultDockerSocketDarwin(t *testing.T) {
|
||||
// Save original HOME
|
||||
originalHome := os.Getenv("HOME")
|
||||
defer func() {
|
||||
os.Setenv("HOME", originalHome)
|
||||
}()
|
||||
|
||||
// Test with HOME set
|
||||
testHome := "/Users/test"
|
||||
os.Setenv("HOME", testHome)
|
||||
expected := "unix://" + filepath.Join(testHome, ".docker/run/docker.sock")
|
||||
result := getDefaultDockerSocket()
|
||||
if result != expected {
|
||||
t.Errorf("Expected %s, got %s", expected, result)
|
||||
}
|
||||
|
||||
// Test with HOME unset
|
||||
os.Unsetenv("HOME")
|
||||
result = getDefaultDockerSocket()
|
||||
if result != "" {
|
||||
t.Errorf("Expected empty string when HOME is unset, got %s", result)
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/image/v5/copy"
|
||||
@ -16,6 +18,21 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// newExpectedSystemContext creates a SystemContext with expected defaults for tests,
|
||||
// accounting for platform-specific behavior like macOS Docker socket location
|
||||
func newExpectedSystemContext() *types.SystemContext {
|
||||
ctx := &types.SystemContext{
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
}
|
||||
// On macOS, DockerDaemonHost gets set to the platform-specific default
|
||||
if runtime.GOOS == "darwin" {
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
ctx.DockerDaemonHost = "unix://" + filepath.Join(home, ".docker/run/docker.sock")
|
||||
}
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func TestNoteCloseFailure(t *testing.T) {
|
||||
const description = "description"
|
||||
|
||||
@ -73,9 +90,7 @@ func TestImageOptionsNewSystemContext(t *testing.T) {
|
||||
opts := fakeImageOptions(t, "dest-", true, []string{}, []string{})
|
||||
res, err := opts.newSystemContext()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &types.SystemContext{
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
}, res)
|
||||
assert.Equal(t, newExpectedSystemContext(), res)
|
||||
|
||||
// Set everything to non-default values.
|
||||
opts = fakeImageOptions(t, "dest-", true, []string{
|
||||
@ -148,9 +163,7 @@ func TestImageDestOptionsNewSystemContext(t *testing.T) {
|
||||
opts := fakeImageDestOptions(t, "dest-", true, []string{}, []string{})
|
||||
res, err := opts.newSystemContext()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &types.SystemContext{
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
}, res)
|
||||
assert.Equal(t, newExpectedSystemContext(), res)
|
||||
|
||||
authFile := "/tmp/auth.json"
|
||||
// Make sure when REGISTRY_AUTH_FILE is set the auth file is used
|
||||
@ -162,10 +175,9 @@ func TestImageDestOptionsNewSystemContext(t *testing.T) {
|
||||
})
|
||||
res, err = opts.newSystemContext()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &types.SystemContext{
|
||||
AuthFilePath: authFile,
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
}, res)
|
||||
expected := newExpectedSystemContext()
|
||||
expected.AuthFilePath = authFile
|
||||
assert.Equal(t, expected, res)
|
||||
|
||||
// Set everything to non-default values.
|
||||
opts = fakeImageDestOptions(t, "dest-", true, []string{
|
||||
@ -255,10 +267,9 @@ func TestImageOptionsUsernamePassword(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, &types.SystemContext{
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
DockerAuthConfig: command.expectedAuthConfig,
|
||||
}, res)
|
||||
expected := newExpectedSystemContext()
|
||||
expected.DockerAuthConfig = command.expectedAuthConfig
|
||||
assert.Equal(t, expected, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -508,9 +519,16 @@ func TestImageOptionsAuthfileOverride(t *testing.T) {
|
||||
res, err := opts.newSystemContext()
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, &types.SystemContext{
|
||||
expected := &types.SystemContext{
|
||||
AuthFilePath: testCase.expectedAuthfilePath,
|
||||
DockerRegistryUserAgent: defaultUserAgent,
|
||||
}, res)
|
||||
}
|
||||
// On macOS, DockerDaemonHost gets set to the platform-specific default
|
||||
if runtime.GOOS == "darwin" {
|
||||
if home := os.Getenv("HOME"); home != "" {
|
||||
expected.DockerDaemonHost = "unix://" + filepath.Join(home, ".docker/run/docker.sock")
|
||||
}
|
||||
}
|
||||
assert.Equal(t, expected, res)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user