@@ -20,6 +20,8 @@ import (
20
20
"context"
21
21
"fmt"
22
22
"os"
23
+ "strings"
24
+ "sync"
23
25
24
26
"github.com/compose-spec/compose-go/types"
25
27
"github.com/containerd/containerd/platforms"
@@ -29,10 +31,12 @@ import (
29
31
"github.com/docker/buildx/util/buildflags"
30
32
xprogress "github.com/docker/buildx/util/progress"
31
33
moby "github.com/docker/docker/api/types"
34
+ "github.com/docker/docker/registry"
32
35
bclient "github.com/moby/buildkit/client"
33
36
"github.com/moby/buildkit/session"
34
37
"github.com/moby/buildkit/session/auth/authprovider"
35
38
specs "github.com/opencontainers/image-spec/specs-go/v1"
39
+ "golang.org/x/sync/errgroup"
36
40
37
41
"github.com/docker/compose-cli/pkg/api"
38
42
"github.com/docker/compose-cli/pkg/progress"
@@ -97,7 +101,7 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types.
97
101
}
98
102
}
99
103
100
- images , err := s .getLocalImagesDigests (ctx , project )
104
+ images , err := s .getLocalImagesIDs (ctx , project )
101
105
if err != nil {
102
106
return err
103
107
}
@@ -163,7 +167,19 @@ func (s *composeService) getBuildOptions(project *types.Project, images map[stri
163
167
164
168
}
165
169
166
- func (s * composeService ) getLocalImagesDigests (ctx context.Context , project * types.Project ) (map [string ]string , error ) {
170
+ func (s * composeService ) getLocalImagesIDs (ctx context.Context , project * types.Project ) (map [string ]string , error ) {
171
+ imgs , err := s .getLocalImageSummaries (ctx , project )
172
+ if err != nil {
173
+ return nil , err
174
+ }
175
+ images := map [string ]string {}
176
+ for name , info := range imgs {
177
+ images [name ] = info .ID
178
+ }
179
+ return images , nil
180
+ }
181
+
182
+ func (s * composeService ) getLocalImageSummaries (ctx context.Context , project * types.Project ) (map [string ]api.ImageSummary , error ) {
167
183
imageNames := []string {}
168
184
for _ , s := range project .Services {
169
185
imgName := getImageName (s , project .Name )
@@ -175,13 +191,64 @@ func (s *composeService) getLocalImagesDigests(ctx context.Context, project *typ
175
191
if err != nil {
176
192
return nil , err
177
193
}
178
- images := map [string ]string {}
179
- for name , info := range imgs {
180
- images [name ] = info .ID
194
+ return imgs , nil
195
+ }
196
+
197
+ func (s * composeService ) getLocalImagesDigests (ctx context.Context , project * types.Project ) (map [string ][]string , error ) {
198
+ imgs , err := s .getLocalImageSummaries (ctx , project )
199
+ if err != nil {
200
+ return nil , err
201
+ }
202
+ images := map [string ][]string {}
203
+ for name , summary := range imgs {
204
+ for _ , d := range summary .Digests {
205
+ s := strings .Split (d , "@" )
206
+ images [name ] = append (images [name ], s [len (s )- 1 ])
207
+ }
181
208
}
182
209
return images , nil
183
210
}
184
211
212
+ func (s * composeService ) getDistributionImagesDigests (ctx context.Context , project * types.Project ) (map [string ]string , error ) {
213
+ images := map [string ]string {}
214
+
215
+ for _ , service := range project .Services {
216
+ if service .Image == "" {
217
+ continue
218
+ }
219
+ images [service .Image ] = ""
220
+ }
221
+
222
+ info , err := s .apiClient .Info (ctx )
223
+ if err != nil {
224
+ return nil , err
225
+ }
226
+
227
+ if info .IndexServerAddress == "" {
228
+ info .IndexServerAddress = registry .IndexServer
229
+ }
230
+
231
+ l := sync.Mutex {}
232
+ eg , ctx := errgroup .WithContext (ctx )
233
+ for img := range images {
234
+ img := img
235
+ eg .Go (func () error {
236
+ registryAuth , err := getEncodedRegistryAuth (img , info , s .configFile )
237
+ if err != nil {
238
+ return err
239
+ }
240
+ inspect , _ := s .apiClient .DistributionInspect (ctx , img , registryAuth )
241
+ // Ignore error here.
242
+ // If you catch error here, all inspect requests will fail.
243
+ l .Lock ()
244
+ images [img ] = inspect .Descriptor .Digest .String ()
245
+ l .Unlock ()
246
+ return nil
247
+ })
248
+ }
249
+ return images , eg .Wait ()
250
+ }
251
+
185
252
func (s * composeService ) doBuild (ctx context.Context , project * types.Project , opts map [string ]build.Options , observedState Containers , mode string ) (map [string ]string , error ) {
186
253
info , err := s .apiClient .Info (ctx )
187
254
if err != nil {
0 commit comments