diff --git a/packages/@aws-cdk/core/lib/asset-staging.ts b/packages/@aws-cdk/core/lib/asset-staging.ts index 96b16554a67f1..6831790d50938 100644 --- a/packages/@aws-cdk/core/lib/asset-staging.ts +++ b/packages/@aws-cdk/core/lib/asset-staging.ts @@ -469,6 +469,7 @@ export class AssetStaging extends Construct { entrypoint: options.entrypoint, workingDirectory: options.workingDirectory ?? AssetStaging.BUNDLING_INPUT_DIR, securityOpt: options.securityOpt ?? '', + volumesFrom: options.volumesFrom, }); } } catch (err) { diff --git a/packages/@aws-cdk/core/lib/bundling.ts b/packages/@aws-cdk/core/lib/bundling.ts index c496bf31d8672..a78f5e8a6aca0 100644 --- a/packages/@aws-cdk/core/lib/bundling.ts +++ b/packages/@aws-cdk/core/lib/bundling.ts @@ -43,6 +43,13 @@ export interface BundlingOptions { */ readonly volumes?: DockerVolume[]; + /** + * Where to mount the specified volumes from + * @see https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from + * @default - no containers are specified to mount volumes from + */ + readonly volumesFrom?: string[]; + /** * The environment variables to pass to the Docker container. * @@ -210,6 +217,9 @@ export class BundlingDockerImage { ...options.user ? ['-u', options.user] : [], + ...options.volumesFrom + ? flatten(options.volumesFrom.map(v => ['--volumes-from', v])) + : [], ...flatten(volumes.map(v => ['-v', `${v.hostPath}:${v.containerPath}:${isSeLinux() ? 'z,' : ''}${v.consistency ?? DockerVolumeConsistency.DELEGATED}`])), ...flatten(Object.entries(environment).map(([k, v]) => ['--env', `${k}=${v}`])), ...options.workingDirectory @@ -441,6 +451,13 @@ export interface DockerRunOptions { */ readonly volumes?: DockerVolume[]; + /** + * Where to mount the specified volumes from + * @see https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container---volumes-from + * @default - no containers are specified to mount volumes from + */ + readonly volumesFrom?: string[]; + /** * The environment variables to pass to the container. * diff --git a/packages/@aws-cdk/core/test/bundling.test.ts b/packages/@aws-cdk/core/test/bundling.test.ts index 49f26d8dab7b2..3879d0b27fc41 100644 --- a/packages/@aws-cdk/core/test/bundling.test.ts +++ b/packages/@aws-cdk/core/test/bundling.test.ts @@ -438,6 +438,44 @@ describe('bundling', () => { ], { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); }); + test('adding user provided docker volume options', () => { + // GIVEN + sinon.stub(process, 'platform').value('darwin'); + const spawnSyncStub = sinon.stub(child_process, 'spawnSync').returns({ + status: 1, + stderr: Buffer.from('stderr'), + stdout: Buffer.from('stdout'), + pid: 123, + output: ['stdout', 'stderr'], + signal: null, + }); + const image = DockerImage.fromRegistry('alpine'); + + try { + image.run({ + command: ['cool', 'command'], + volumesFrom: ['foo', 'bar'], + volumes: [{ hostPath: '/host-path', containerPath: '/container-path' }], + workingDirectory: '/working-directory', + user: 'user:group', + }); + } catch (e) { + // We expect this to fail as the test environment will not have the required docker setup for the command to exit successfully + // nevertheless what we want to check here is that the command was built correctly and triggered + }; + + expect(spawnSyncStub.calledWith('docker', [ + 'run', '--rm', + '-u', 'user:group', + '--volumes-from', 'foo', + '--volumes-from', 'bar', + '-v', '/host-path:/container-path:delegated', + '-w', '/working-directory', + 'alpine', + 'cool', 'command', + ], { stdio: ['ignore', process.stderr, 'inherit'] })).toEqual(true); + }); + test('ensure selinux docker mount', () => { // GIVEN sinon.stub(process, 'platform').value('linux');