@@ -386,7 +386,7 @@ async function startContainer(params: DockerResolverParameters, buildParams: Doc
386
386
// Save override docker-compose file to disk.
387
387
// Persisted folder is a path that will be maintained between sessions
388
388
// Note: As a fallback, persistedFolder is set to the build's tmpDir() directory
389
- const overrideFilePath = await writeFeaturesComposeOverrideFile ( updatedImageName , currentImageName , mergedConfig , config , versionPrefix , imageDetails , service , idLabels , params . additionalMounts , persistedFolder , featuresStartOverrideFilePrefix , buildCLIHost , output ) ;
389
+ const overrideFilePath = await writeFeaturesComposeOverrideFile ( updatedImageName , currentImageName , mergedConfig , config , versionPrefix , imageDetails , service , idLabels , params . additionalMounts , persistedFolder , featuresStartOverrideFilePrefix , buildCLIHost , params , output ) ;
390
390
if ( overrideFilePath ) {
391
391
// Add file path to override file as parameter
392
392
composeGlobalArgs . push ( '-f' , overrideFilePath ) ;
@@ -449,9 +449,10 @@ async function writeFeaturesComposeOverrideFile(
449
449
overrideFilePath : string ,
450
450
overrideFilePrefix : string ,
451
451
buildCLIHost : CLIHost ,
452
+ params : DockerResolverParameters ,
452
453
output : Log ,
453
454
) {
454
- const composeOverrideContent = await generateFeaturesComposeOverrideContent ( updatedImageName , originalImageName , mergedConfig , config , versionPrefix , imageDetails , service , additionalLabels , additionalMounts ) ;
455
+ const composeOverrideContent = await generateFeaturesComposeOverrideContent ( updatedImageName , originalImageName , mergedConfig , config , versionPrefix , imageDetails , service , additionalLabels , additionalMounts , params ) ;
455
456
const overrideFileHasContents = ! ! composeOverrideContent && composeOverrideContent . length > 0 && composeOverrideContent . trim ( ) !== '' ;
456
457
if ( overrideFileHasContents ) {
457
458
output . write ( `Docker Compose override file for creating container:\n${ composeOverrideContent } ` ) ;
@@ -470,6 +471,12 @@ async function writeFeaturesComposeOverrideFile(
470
471
}
471
472
}
472
473
474
+ async function checkDockerSupportForGPU ( params : DockerCLIParameters | DockerResolverParameters ) : Promise < Boolean > {
475
+ const result = await dockerCLI ( params , 'info' , '-f' , '{{.Runtimes.nvidia}}' ) ;
476
+ const runtimeFound = result . stdout . includes ( 'nvidia-container-runtime' ) ;
477
+ return runtimeFound ;
478
+ }
479
+
473
480
async function generateFeaturesComposeOverrideContent (
474
481
updatedImageName : string ,
475
482
originalImageName : string ,
@@ -480,6 +487,7 @@ async function generateFeaturesComposeOverrideContent(
480
487
service : any ,
481
488
additionalLabels : string [ ] ,
482
489
additionalMounts : Mount [ ] ,
490
+ params : DockerResolverParameters ,
483
491
) {
484
492
const overrideImage = updatedImageName !== originalImageName ;
485
493
@@ -501,6 +509,19 @@ async function generateFeaturesComposeOverrideContent(
501
509
const userCommand = overrideCommand ? [ ] : composeCommand /* $ already escaped. */
502
510
|| ( composeEntrypoint ? [ /* Ignore image CMD per docker-compose.yml spec. */ ] : ( ( await imageDetails ( ) ) . Config . Cmd || [ ] ) . map ( c => c . replace ( / \$ / g, '$$$$' ) ) ) ; // $ > $$ to escape docker-compose.yml's interpolation.
503
511
512
+ const hasGpuRequirement = config . hostRequirements ?. gpu ;
513
+ const addGpuCapability = hasGpuRequirement && await checkDockerSupportForGPU ( params ) ;
514
+ if ( hasGpuRequirement && hasGpuRequirement !== 'optional' && ! addGpuCapability ) {
515
+ throw Error ( 'Unable to detect GPU yet a GPU was required - consider marking it as "optional"' ) ;
516
+ }
517
+ const gpuResources = addGpuCapability ? '' : `
518
+ deploy:
519
+ resources:
520
+ reservations:
521
+ devices:
522
+ - capabilities: [gpu]
523
+ ` ;
524
+
504
525
return `${ versionPrefix } services:
505
526
'${ config . service } ':${ overrideImage ? `
506
527
image: ${ updatedImageName } ` : '' }
@@ -524,7 +545,7 @@ while sleep 1 & wait $$!; do :; done", "-"${userEntrypoint.map(a => `, ${JSON.st
524
545
volumes:${ mounts . map ( m => `
525
546
- ${ m . source } :${ m . target } ` ) . join ( '' ) } ` : '' } ${ volumeMounts . length ? `
526
547
volumes:${ volumeMounts . map ( m => `
527
- ${ m . source } :${ m . external ? '\n external: true' : '' } ` ) . join ( '' ) } ` : '' }
548
+ ${ m . source } :${ m . external ? '\n external: true' : '' } ` ) . join ( '' ) } ` : '' } ${ gpuResources }
528
549
` ;
529
550
}
530
551
0 commit comments