@@ -307,19 +307,62 @@ public function buildApiUrl(string $dockerUrl, string $route): string {
307307 return sprintf ('%s/%s/%s ' , $ dockerUrl , self ::DOCKER_API_VERSION , $ route );
308308 }
309309
310- public function buildBaseImageName (array $ imageParams ): string {
310+ public function buildBaseImageName (array $ imageParams , DaemonConfig $ daemonConfig ): string {
311+ $ deployConfig = $ daemonConfig ->getDeployConfig ();
312+ if (isset ($ deployConfig ['registries ' ])) { // custom Docker registry, overrides ExApp's image_src
313+ foreach ($ deployConfig ['registries ' ] as $ registry ) {
314+ if ($ registry ['from ' ] === $ imageParams ['image_src ' ] && $ registry ['to ' ] !== 'local ' ) { // local target skips image pull, imageId should be unchanged
315+ $ imageParams ['image_src ' ] = rtrim ($ registry ['to ' ], '/ ' );
316+ break ;
317+ }
318+ }
319+ }
311320 return $ imageParams ['image_src ' ] . '/ ' .
312321 $ imageParams ['image_name ' ] . ': ' . $ imageParams ['image_tag ' ];
313322 }
314323
315324 private function buildExtendedImageName (array $ imageParams , DaemonConfig $ daemonConfig ): ?string {
316- if (empty ($ daemonConfig ->getDeployConfig ()['computeDevice ' ]['id ' ])) {
325+ $ deployConfig = $ daemonConfig ->getDeployConfig ();
326+ if (empty ($ deployConfig ['computeDevice ' ]['id ' ])) {
317327 return null ;
318328 }
329+ if (isset ($ deployConfig ['registries ' ])) { // custom Docker registry, overrides ExApp's image_src
330+ foreach ($ deployConfig ['registries ' ] as $ registry ) {
331+ if ($ registry ['from ' ] === $ imageParams ['image_src ' ] && $ registry ['to ' ] !== 'local ' ) { // local target skips image pull, imageId should be unchanged
332+ $ imageParams ['image_src ' ] = rtrim ($ registry ['to ' ], '/ ' );
333+ break ;
334+ }
335+ }
336+ }
319337 return $ imageParams ['image_src ' ] . '/ ' .
320338 $ imageParams ['image_name ' ] . ': ' . $ imageParams ['image_tag ' ] . '- ' . $ daemonConfig ->getDeployConfig ()['computeDevice ' ]['id ' ];
321339 }
322340
341+ private function shouldPullImage (array $ imageParams , DaemonConfig $ daemonConfig ): bool {
342+ $ deployConfig = $ daemonConfig ->getDeployConfig ();
343+ if (isset ($ deployConfig ['registries ' ])) { // custom Docker registry, overrides ExApp's image_src
344+ foreach ($ deployConfig ['registries ' ] as $ registry ) {
345+ if ($ registry ['from ' ] === $ imageParams ['image_src ' ] && $ registry ['to ' ] === 'local ' ) { // local target skips image pull, imageId should be unchanged
346+ return false ;
347+ }
348+ }
349+ }
350+ return true ;
351+ }
352+
353+ public function imageExists (string $ dockerUrl , string $ imageId ): bool {
354+ $ url = $ this ->buildApiUrl ($ dockerUrl , sprintf ('images/%s/json ' , $ imageId ));
355+ try {
356+ $ response = $ this ->guzzleClient ->get ($ url );
357+ return $ response ->getStatusCode () === 200 ;
358+ } catch (GuzzleException $ e ) {
359+ if ($ e ->getCode () !== 404 ) {
360+ $ this ->logger ->error ('Failed to check image existence ' , ['exception ' => $ e ]);
361+ }
362+ return false ;
363+ }
364+ }
365+
323366 public function createContainer (string $ dockerUrl , string $ imageId , DaemonConfig $ daemonConfig , array $ params = []): array {
324367 $ createVolumeResult = $ this ->createVolume ($ dockerUrl , $ this ->buildExAppVolumeName ($ params ['name ' ]));
325368 if (isset ($ createVolumeResult ['error ' ])) {
@@ -459,28 +502,48 @@ public function removeContainer(string $dockerUrl, string $containerId): string
459502 public function pullImage (
460503 string $ dockerUrl , array $ params , ExApp $ exApp , int $ startPercent , int $ maxPercent , DaemonConfig $ daemonConfig , string &$ imageId
461504 ): string {
505+ $ shouldPull = $ this ->shouldPullImage ($ params , $ daemonConfig );
462506 $ urlToLog = $ this ->useSocket ? $ this ->socketAddress : $ dockerUrl ;
463507 $ imageId = $ this ->buildExtendedImageName ($ params , $ daemonConfig );
508+
464509 if ($ imageId ) {
465510 try {
466- $ r = $ this ->pullImageInternal ($ dockerUrl , $ exApp , $ startPercent , $ maxPercent , $ imageId );
467- if ($ r === '' ) {
468- $ this ->logger ->info (sprintf ('Successfully pulled "extended" image: %s ' , $ imageId ));
511+ if ($ shouldPull ) {
512+ $ r = $ this ->pullImageInternal ($ dockerUrl , $ exApp , $ startPercent , $ maxPercent , $ imageId );
513+ if ($ r === '' ) {
514+ $ this ->logger ->info (sprintf ('Successfully pulled "extended" image: %s ' , $ imageId ));
515+ return '' ;
516+ }
517+ $ this ->logger ->info (sprintf ('Failed to pull "extended" image(%s): %s ' , $ imageId , $ r ));
518+ } elseif ($ this ->imageExists ($ dockerUrl , $ imageId )) {
519+ $ this ->logger ->info ('Daemon registry mapping set to "local", skipping image pull ' );
520+ $ this ->exAppService ->setAppDeployProgress ($ exApp , $ maxPercent );
469521 return '' ;
522+ } else {
523+ $ this ->logger ->info (sprintf ('Image(%s) not found, but daemon registry mapping set to "local", trying base image ' , $ imageId ));
470524 }
471- $ this ->logger ->info (sprintf ('Failed to pull "extended" image(%s): %s ' , $ imageId , $ r ));
472525 } catch (GuzzleException $ e ) {
473526 $ this ->logger ->info (
474527 sprintf ('Failed to pull "extended" image via "%s", GuzzleException occur: %s ' , $ urlToLog , $ e ->getMessage ())
475528 );
476529 }
477530 }
478- $ imageId = $ this -> buildBaseImageName ( $ params );
479- $ this ->logger -> info ( sprintf ( ' Pulling "base" image: %s ' , $ imageId ) );
531+
532+ $ imageId = $ this ->buildBaseImageName ( $ params , $ daemonConfig );
480533 try {
481- $ r = $ this ->pullImageInternal ($ dockerUrl , $ exApp , $ startPercent , $ maxPercent , $ imageId );
482- if ($ r === '' ) {
483- $ this ->logger ->info (sprintf ('Image(%s) pulled successfully. ' , $ imageId ));
534+ if ($ shouldPull ) {
535+ $ this ->logger ->info (sprintf ('Pulling "base" image: %s ' , $ imageId ));
536+ $ r = $ this ->pullImageInternal ($ dockerUrl , $ exApp , $ startPercent , $ maxPercent , $ imageId );
537+ if ($ r === '' ) {
538+ $ this ->logger ->info (sprintf ('Image(%s) pulled successfully. ' , $ imageId ));
539+ }
540+ } elseif ($ this ->imageExists ($ dockerUrl , $ imageId )) {
541+ $ this ->logger ->info ('Daemon registry mapping set to "local", skipping image pull ' );
542+ $ this ->exAppService ->setAppDeployProgress ($ exApp , $ maxPercent );
543+ return '' ;
544+ } else {
545+ $ this ->logger ->warning (sprintf ('Image(%s) not found, but daemon registry mapping set to "local", skipping image pull ' , $ imageId ));
546+ return '' ;
484547 }
485548 } catch (GuzzleException $ e ) {
486549 $ r = sprintf ('Failed to pull image via "%s", GuzzleException occur: %s ' , $ urlToLog , $ e ->getMessage ());
0 commit comments