Skip to content

Commit 3c9d134

Browse files
committed
Fix version lock issue
1 parent f4fc366 commit 3c9d134

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

pkg/commands/docker.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,21 @@ func (c *DockerCommand) NewCommandObject(obj CommandObject) CommandObject {
7070
return defaultObj
7171
}
7272

73+
// newDockerClient creates a Docker client with the given host.
74+
// We avoid using client.FromEnv because it includes WithVersionFromEnv() which
75+
// sets manualOverride=true when DOCKER_API_VERSION is set, preventing API version
76+
// negotiation even when WithAPIVersionNegotiation() is specified.
77+
// Instead, we explicitly configure only what we need, and rely on proper
78+
// API version negotiation to support older Docker daemons.
79+
// See https://github.com/jesseduffield/lazydocker/issues/715
80+
func newDockerClient(dockerHost string) (*client.Client, error) {
81+
return client.NewClientWithOpts(
82+
client.WithTLSClientConfigFromEnv(),
83+
client.WithAPIVersionNegotiation(),
84+
client.WithHost(dockerHost),
85+
)
86+
}
87+
7388
// NewDockerCommand it runs docker commands
7489
func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*DockerCommand, error) {
7590
dockerHost, err := determineDockerHost()
@@ -96,7 +111,7 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat
96111
dockerHost = dockerHostFromEnv
97112
}
98113

99-
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation(), client.WithHost(dockerHost))
114+
cli, err := newDockerClient(dockerHost)
100115
if err != nil {
101116
ogLog.Fatal(err)
102117
}

pkg/commands/docker_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package commands
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/docker/docker/client"
8+
"github.com/stretchr/testify/assert"
9+
)
10+
11+
// TestNewDockerClientVersionNegotiation verifies that newDockerClient allows
12+
// API version negotiation even when DOCKER_API_VERSION is set.
13+
//
14+
// This is a regression test for https://github.com/jesseduffield/lazydocker/issues/715
15+
// where users got "client version 1.25 is too old" errors because FromEnv()
16+
// includes WithVersionFromEnv() which sets manualOverride=true, preventing
17+
// API version negotiation.
18+
func TestNewDockerClientVersionNegotiation(t *testing.T) {
19+
// Save original env var and restore after test
20+
originalAPIVersion := os.Getenv("DOCKER_API_VERSION")
21+
defer func() {
22+
if originalAPIVersion == "" {
23+
os.Unsetenv("DOCKER_API_VERSION")
24+
} else {
25+
os.Setenv("DOCKER_API_VERSION", originalAPIVersion)
26+
}
27+
}()
28+
29+
// Set DOCKER_API_VERSION to an old version that would cause
30+
// "client version 1.25 is too old" errors if negotiation is disabled
31+
os.Setenv("DOCKER_API_VERSION", "1.25")
32+
33+
t.Run("FromEnv locks version preventing negotiation", func(t *testing.T) {
34+
// This demonstrates the problematic behavior we're avoiding.
35+
// When using FromEnv with DOCKER_API_VERSION set, the client
36+
// version gets locked to 1.25 and negotiation is disabled.
37+
cli, err := client.NewClientWithOpts(
38+
client.FromEnv,
39+
client.WithAPIVersionNegotiation(),
40+
)
41+
assert.NoError(t, err)
42+
defer cli.Close()
43+
44+
// Version is locked to the env var value
45+
assert.Equal(t, "1.25", cli.ClientVersion())
46+
})
47+
48+
t.Run("newDockerClient allows version negotiation", func(t *testing.T) {
49+
// Test the actual production function.
50+
// Use DefaultDockerHost for cross-platform compatibility
51+
// (unix socket on Linux/macOS, named pipe on Windows).
52+
cli, err := newDockerClient(client.DefaultDockerHost)
53+
assert.NoError(t, err)
54+
defer cli.Close()
55+
56+
// Version is NOT locked to the env var value (1.25).
57+
// Instead, it uses the library's default version and will negotiate
58+
// with the server on first request. This is the key difference that
59+
// fixes the "version too old" error.
60+
assert.NotEqual(t, "1.25", cli.ClientVersion(),
61+
"client version should not be locked to DOCKER_API_VERSION env var")
62+
})
63+
}

0 commit comments

Comments
 (0)