@@ -24,6 +24,7 @@ import (
2424 "fmt"
2525 "io"
2626 "strings"
27+ "time"
2728
2829 "github.com/compose-spec/compose-go/v2/types"
2930 "github.com/distribution/reference"
@@ -153,7 +154,7 @@ func (s *composeService) pull(ctx context.Context, project *types.Project, opts
153154 return multierror .Append (nil , pullErrors ... ).ErrorOrNil ()
154155}
155156
156- func imageAlreadyPresent (serviceImage string , localImages map [string ]string ) bool {
157+ func imageAlreadyPresent (serviceImage string , localImages map [string ]api. ImageSummary ) bool {
157158 normalizedImage , err := reference .ParseDockerRef (serviceImage )
158159 if err != nil {
159160 return false
@@ -288,23 +289,16 @@ func encodedAuth(ref reference.Named, configFile driver.Auth) (string, error) {
288289 return base64 .URLEncoding .EncodeToString (buf ), nil
289290}
290291
291- func (s * composeService ) pullRequiredImages (ctx context.Context , project * types.Project , images map [string ]string , quietPull bool ) error {
292+ func (s * composeService ) pullRequiredImages (ctx context.Context , project * types.Project , images map [string ]api. ImageSummary , quietPull bool ) error {
292293 var needPull []types.ServiceConfig
293294 for _ , service := range project .Services {
294- if service .Image == "" {
295- continue
295+ pull , err := mustPull (service , images )
296+ if err != nil {
297+ return err
296298 }
297- switch service .PullPolicy {
298- case "" , types .PullPolicyMissing , types .PullPolicyIfNotPresent :
299- if _ , ok := images [service .Image ]; ok {
300- continue
301- }
302- case types .PullPolicyNever , types .PullPolicyBuild :
303- continue
304- case types .PullPolicyAlways :
305- // force pull
299+ if pull {
300+ needPull = append (needPull , service )
306301 }
307- needPull = append (needPull , service )
308302 }
309303 if len (needPull ) == 0 {
310304 return nil
@@ -314,11 +308,15 @@ func (s *composeService) pullRequiredImages(ctx context.Context, project *types.
314308 w := progress .ContextWriter (ctx )
315309 eg , ctx := errgroup .WithContext (ctx )
316310 eg .SetLimit (s .maxConcurrency )
317- pulledImages := make ([]string , len (needPull ))
311+ pulledImages := make ([]api. ImageSummary , len (needPull ))
318312 for i , service := range needPull {
319313 eg .Go (func () error {
320314 id , err := s .pullServiceImage (ctx , service , s .configFile (), w , quietPull , project .Environment ["DOCKER_DEFAULT_PLATFORM" ])
321- pulledImages [i ] = id
315+ pulledImages [i ] = api.ImageSummary {
316+ ID : id ,
317+ Repository : service .Image ,
318+ LastTagTime : time .Now (),
319+ }
322320 if err != nil && isServiceImageToBuild (service , project .Services ) {
323321 // image can be built, so we can ignore pull failure
324322 return nil
@@ -328,14 +326,40 @@ func (s *composeService) pullRequiredImages(ctx context.Context, project *types.
328326 }
329327 err := eg .Wait ()
330328 for i , service := range needPull {
331- if pulledImages [i ] != "" {
329+ if pulledImages [i ]. ID != "" {
332330 images [service .Image ] = pulledImages [i ]
333331 }
334332 }
335333 return err
336334 }, s .stdinfo ())
337335}
338336
337+ func mustPull (service types.ServiceConfig , images map [string ]api.ImageSummary ) (bool , error ) {
338+ if service .Image == "" {
339+ return false , nil
340+ }
341+ policy , duration , err := service .GetPullPolicy ()
342+ if err != nil {
343+ return false , err
344+ }
345+ switch policy {
346+ case types .PullPolicyAlways :
347+ // force pull
348+ return true , nil
349+ case types .PullPolicyNever , types .PullPolicyBuild :
350+ return false , nil
351+ case types .PullPolicyRefresh :
352+ img , ok := images [service .Image ]
353+ if ! ok {
354+ return true , nil
355+ }
356+ return time .Now ().After (img .LastTagTime .Add (duration )), nil
357+ default : // Pull if missing
358+ _ , ok := images [service .Image ]
359+ return ! ok , nil
360+ }
361+ }
362+
339363func isServiceImageToBuild (service types.ServiceConfig , services types.Services ) bool {
340364 if service .Build != nil {
341365 return true
0 commit comments