@@ -4,12 +4,17 @@ import (
4
4
"context"
5
5
"errors"
6
6
"fmt"
7
+ "os"
7
8
"strings"
8
9
10
+ dockercommand "github.com/docker/cli/cli/command"
11
+ dockerconfig "github.com/docker/cli/cli/config"
9
12
"github.com/docker/compose/v2/pkg/progress"
10
13
"github.com/docker/docker/api/types/container"
14
+ "github.com/docker/docker/api/types/registry"
11
15
dockerclient "github.com/docker/docker/client"
12
16
"github.com/docker/docker/pkg/jsonmessage"
17
+ "github.com/psviderski/uncloud/internal/machine/docker"
13
18
"github.com/psviderski/uncloud/internal/secret"
14
19
"github.com/psviderski/uncloud/pkg/api"
15
20
"google.golang.org/grpc/status"
@@ -89,7 +94,14 @@ func (cli *Client) pullImageWithProgress(ctx context.Context, image, machineName
89
94
StatusText : "Pulling" ,
90
95
})
91
96
92
- pullCh , err := cli .Docker .PullImage (ctx , image )
97
+ opts := docker.PullOptions {}
98
+ // Try to retrieve the authentication token for the image from the default local Docker config file.
99
+ if encodedAuth , err := retrieveRegistryAuthFromDocker (image ); err == nil && encodedAuth != "" {
100
+ // If RegistryAuth is empty, Uncloud daemon will try to retrieve the credentials from its own Docker config.
101
+ opts .RegistryAuth = encodedAuth
102
+ }
103
+
104
+ pullCh , err := cli .Docker .PullImage (ctx , image , opts )
93
105
if err != nil {
94
106
statusErr := status .Convert (err )
95
107
pw .Event (progress.Event {
@@ -143,6 +155,34 @@ func (cli *Client) pullImageWithProgress(ctx context.Context, image, machineName
143
155
return nil
144
156
}
145
157
158
+ // retrieveRegistryAuthFromDocker retrieves the authentication token for the specified image from the local Docker
159
+ // config file. It returns the encoded authentication token if it contains any credentials, or an empty string if
160
+ // no credentials are found.
161
+ func retrieveRegistryAuthFromDocker (image string ) (string , error ) {
162
+ // Try to retrieve the authentication token for the image from the default local Docker config file.
163
+ dockerConfig := dockerconfig .LoadDefaultConfigFile (os .Stderr )
164
+ encodedAuth , err := dockercommand .RetrieveAuthTokenFromImage (dockerConfig , image )
165
+ if err != nil {
166
+ return "" , err
167
+ }
168
+ // The encodedAuth can be a base64-encoded "{}" (empty JSON object) or include a server address but no credentials.
169
+ // Return encodedAuth only if it contains any credentials.
170
+ auth , err := registry .DecodeAuthConfig (encodedAuth )
171
+ if err != nil {
172
+ return "" , fmt .Errorf ("decode auth config: %w" , err )
173
+ }
174
+
175
+ if auth .Username == "" &&
176
+ auth .Password == "" &&
177
+ auth .Auth == "" &&
178
+ auth .IdentityToken == "" &&
179
+ auth .RegistryToken == "" {
180
+ return "" , nil
181
+ }
182
+
183
+ return encodedAuth , nil
184
+ }
185
+
146
186
// toPullProgressEvent converts a JSON progress message from the Docker API to a progress event.
147
187
// It's based on toPullProgressEvent from Docker Compose.
148
188
func toPullProgressEvent (jm jsonmessage.JSONMessage ) * progress.Event {
0 commit comments