Skip to content

Commit a0c7dd6

Browse files
AlexKantor87claude
andauthored
fix: add Docker API version negotiation to all client calls (#761)
The Docker SDK bump (v28.0.4 → v28.3.2) changed the default API version from 1.48 to 1.51, breaking Docker operations on hosts with older daemons. - Add WithAPIVersionNegotiation() to all 8 Docker client creation sites - Remove DOCKER_API_VERSION pin from test.yml so CI naturally catches missing negotiation in future Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent b7e060d commit a0c7dd6

4 files changed

Lines changed: 17 additions & 11 deletions

File tree

.github/workflows/test.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ jobs:
163163
INTEGRATION_TEST_AZURE_CLIENT_SECRET: ${{ secrets.azure_client_secret }}
164164
INTEGRATION_TEST_AZURE_CLIENT_ID: ${{ secrets.azure_client_id }}
165165
KOSLI_SONAR_API_TOKEN: ${{ secrets.sonarqube_token }}
166-
DOCKER_API_VERSION: "1.45"
167166
KOSLI_API_TOKEN_PROD: ${{ secrets.kosli_querying_api_token }}
168167
run: |
169168
# some tests use git operations, therefore the git author on the CI VM needs to be set
@@ -273,4 +272,3 @@ jobs:
273272
--trail ${{ inputs.TRAIL_NAME }}
274273
--scan-results snyk-dependency.json
275274
--org ${{ inputs.KOSLI_ORG }}
276-

cmd/kosli/snapshotDocker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func (o *snapshotDockerOptions) run(args []string) error {
8888

8989
func CreateDockerArtifactsData() ([]*server.ServerData, error) {
9090
result := []*server.ServerData{}
91-
cli, err := client.NewClientWithOpts(client.FromEnv)
91+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
9292
if err != nil {
9393
return result, err
9494
}

internal/digest/digest.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ func FileSha256(filepath string, logger *logger.Logger) (string, error) {
251251
// It requires the docker daemon to be accessible and the docker image to be locally present.
252252
// The docker image must have been pushed into a registry to have a digest.
253253
func DockerImageSha256(imageID string) (string, error) {
254-
cli, err := client.NewClientWithOpts(client.FromEnv)
254+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
255255
if err != nil {
256256
return "", err
257257
}
@@ -323,7 +323,7 @@ func requestManifestFromRegistry(registryEndPoint, imageName, imageTag, registry
323323
// RemoteDockerImageSha256 returns a sha256 digest of a docker image by reading it from
324324
// remote docker registry
325325
func RemoteDockerImageSha256(imageName, imageTag, registryEndPoint, registryToken string, logger *logger.Logger) (string, error) {
326-
// Some docker images have Manifest list, aka fat manifest which combines
326+
// Some docker images have Manifest list, aka "fat manifest" which combines
327327
// image manifests for one or more platforms. Other images don't have such manifest.
328328
// The response Content-Type header specifies whether an image has it or not.
329329
// More details here: https://docs.docker.com/registry/spec/manifest-v2-2/

internal/docker/docker.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,17 @@ import (
1414
"github.com/docker/docker/client"
1515
)
1616

17+
// newDockerClient creates a Docker client with API version negotiation enabled.
18+
// This ensures the client automatically downgrades its API version to match
19+
// the daemon, preventing "client version X is too new" errors when the SDK
20+
// is newer than the Docker Engine.
21+
func newDockerClient() (*client.Client, error) {
22+
return client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
23+
}
24+
1725
// PullDockerImage pulls a docker image or returns an error
1826
func PullDockerImage(imageName string) error {
19-
cli, err := client.NewClientWithOpts(client.FromEnv)
27+
cli, err := newDockerClient()
2028
if err != nil {
2129
return err
2230
}
@@ -41,7 +49,7 @@ func PullDockerImage(imageName string) error {
4149

4250
// PushDockerImage pushes a docker image to the local registry or returns an error
4351
func PushDockerImage(imageName string) error {
44-
cli, err := client.NewClientWithOpts(client.FromEnv)
52+
cli, err := newDockerClient()
4553
if err != nil {
4654
return err
4755
}
@@ -73,7 +81,7 @@ func PushDockerImage(imageName string) error {
7381

7482
// TagDockerImage tags a docker image or returns an error
7583
func TagDockerImage(sourceName, targetName string) error {
76-
cli, err := client.NewClientWithOpts(client.FromEnv)
84+
cli, err := newDockerClient()
7785
if err != nil {
7886
return err
7987
}
@@ -83,7 +91,7 @@ func TagDockerImage(sourceName, targetName string) error {
8391

8492
// RemoveDockerImage deletes a docker image or return an error
8593
func RemoveDockerImage(imageName string) error {
86-
cli, err := client.NewClientWithOpts(client.FromEnv)
94+
cli, err := newDockerClient()
8795
if err != nil {
8896
return err
8997
}
@@ -98,7 +106,7 @@ func RemoveDockerImage(imageName string) error {
98106

99107
// RunDockerContainer runs a docker container that sleeps for 6 minutes and returns its ID or returns an error
100108
func RunDockerContainer(imageName string) (string, error) {
101-
cli, err := client.NewClientWithOpts(client.FromEnv)
109+
cli, err := newDockerClient()
102110
if err != nil {
103111
return "", err
104112
}
@@ -117,7 +125,7 @@ func RunDockerContainer(imageName string) (string, error) {
117125

118126
// RemoveDockerContainer remove a docker container or returns an error
119127
func RemoveDockerContainer(containerID string) error {
120-
cli, err := client.NewClientWithOpts(client.FromEnv)
128+
cli, err := newDockerClient()
121129
if err != nil {
122130
return err
123131
}

0 commit comments

Comments
 (0)