diff --git a/packages/@aws-cdk/aws-ecr-assets/README.md b/packages/@aws-cdk/aws-ecr-assets/README.md index 32059529f1ee1..26c3963afbe05 100644 --- a/packages/@aws-cdk/aws-ecr-assets/README.md +++ b/packages/@aws-cdk/aws-ecr-assets/README.md @@ -121,6 +121,18 @@ const asset = new DockerImageAsset(this, 'MyBuildImage', { }) ``` +You can optionally pass cache from and cache to options to cache images: + +```ts +import { DockerImageAsset, Platform } from '@aws-cdk/aws-ecr-assets'; + +const asset = new DockerImageAsset(this, 'MyBuildImage', { + directory: path.join(__dirname, 'my-image'), + cacheFrom: [{ type: 'registry', params: { ref: 'ghcr.io/myorg/myimage:cache' }}], + cacheTo: { type: 'registry', params: { ref: 'ghcr.io/myorg/myimage:cache', mode: 'max', compression: 'zstd' }} +}) +``` + ## Images from Tarball Images are loaded from a local tarball, uploaded to ECR by the CDK toolkit and/or your app's CI-CD pipeline, and can be diff --git a/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts b/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts index da03e18f80046..49e93ff47bbfb 100644 --- a/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts +++ b/packages/@aws-cdk/aws-ecr-assets/lib/image-asset.ts @@ -148,6 +148,28 @@ export interface DockerImageAssetInvalidationOptions { readonly outputs?: boolean; } +/** + * Options for configuring the Docker cache backend + */ +export interface DockerCacheOption { + /** + * The type of cache to use. + * Refer to https://docs.docker.com/build/cache/backends/ for full list of backends. + * @default - unspecified + * + * @example 'registry' + */ + readonly type: string; + /** + * Any parameters to pass into the docker cache backend configuration. + * Refer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. + * @default {} No options provided + * + * @example { ref: `12345678.dkr.ecr.us-west-2.amazonaws.com/cache:${branch}`, mode: "max" } + */ + readonly params?: { [key: string]: string }; +} + /** * Options for DockerImageAsset */ @@ -236,6 +258,22 @@ export interface DockerImageAssetOptions extends FingerprintOptions, FileFingerp * @see https://docs.docker.com/engine/reference/commandline/build/#custom-build-outputs */ readonly outputs?: string[]; + + /** + * Cache from options to pass to the `docker build` command. + * + * @default - no cache from options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheFrom?: DockerCacheOption[]; + + /** + * Cache to options to pass to the `docker build` command. + * + * @default - no cache to options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheTo?: DockerCacheOption; } /** @@ -316,6 +354,16 @@ export class DockerImageAsset extends Construct implements IAsset { */ private readonly dockerOutputs?: string[]; + /** + * Cache from options to pass to the `docker build` command. + */ + private readonly dockerCacheFrom?: DockerCacheOption[]; + + /** + * Cache to options to pass to the `docker build` command. + */ + private readonly dockerCacheTo?: DockerCacheOption; + /** * Docker target to build to */ @@ -407,6 +455,8 @@ export class DockerImageAsset extends Construct implements IAsset { this.dockerBuildSecrets = props.buildSecrets; this.dockerBuildTarget = props.target; this.dockerOutputs = props.outputs; + this.dockerCacheFrom = props.cacheFrom; + this.dockerCacheTo = props.cacheTo; const location = stack.synthesizer.addDockerImageAsset({ directoryName: this.assetPath, @@ -418,6 +468,8 @@ export class DockerImageAsset extends Construct implements IAsset { networkMode: props.networkMode?.mode, platform: props.platform?.platform, dockerOutputs: this.dockerOutputs, + dockerCacheFrom: this.dockerCacheFrom, + dockerCacheTo: this.dockerCacheTo, }); this.repository = ecr.Repository.fromRepositoryName(this, 'Repository', location.repositoryName); @@ -456,6 +508,8 @@ export class DockerImageAsset extends Construct implements IAsset { resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_DOCKER_BUILD_TARGET_KEY] = this.dockerBuildTarget; resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_PROPERTY_KEY] = resourceProperty; resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_DOCKER_OUTPUTS_KEY] = this.dockerOutputs; + resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_DOCKER_CACHE_FROM_KEY] = this.dockerCacheFrom; + resource.cfnOptions.metadata[cxapi.ASSET_RESOURCE_METADATA_DOCKER_CACHE_TO_KEY] = this.dockerCacheTo; } } diff --git a/packages/@aws-cdk/aws-ecr-assets/test/build-image-cache.test.ts b/packages/@aws-cdk/aws-ecr-assets/test/build-image-cache.test.ts new file mode 100644 index 0000000000000..e50c41c4c6f95 --- /dev/null +++ b/packages/@aws-cdk/aws-ecr-assets/test/build-image-cache.test.ts @@ -0,0 +1,88 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { AssetManifest } from '@aws-cdk/cloud-assembly-schema'; +import { App, Stack } from '@aws-cdk/core'; +import { AssetManifestArtifact, CloudArtifact, CloudAssembly } from '@aws-cdk/cx-api'; +import { DockerImageAsset } from '../lib'; + +describe('build cache', () => { + test('manifest contains cache from options ', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app); + const asset = new DockerImageAsset(stack, 'DockerImage6', { + directory: path.join(__dirname, 'demo-image'), + cacheFrom: [{ type: 'registry', params: { image: 'foo' } }], + }); + + // WHEN + const asm = app.synth(); + + // THEN + const manifestArtifact = getAssetManifest(asm); + const manifest = readAssetManifest(manifestArtifact); + + expect(Object.keys(manifest.dockerImages ?? {}).length).toBe(1); + expect(manifest.dockerImages?.[asset.assetHash]?.source.cacheFrom?.length).toBe(1); + expect(manifest.dockerImages?.[asset.assetHash]?.source.cacheFrom?.[0]).toStrictEqual({ + type: 'registry', + params: { image: 'foo' }, + }); + }); + test('manifest contains cache to options ', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app); + const asset = new DockerImageAsset(stack, 'DockerImage6', { + directory: path.join(__dirname, 'demo-image'), + cacheTo: { type: 'inline' }, + }); + + // WHEN + const asm = app.synth(); + + // THEN + const manifestArtifact = getAssetManifest(asm); + const manifest = readAssetManifest(manifestArtifact); + + expect(Object.keys(manifest.dockerImages ?? {}).length).toBe(1); + expect(manifest.dockerImages?.[asset.assetHash]?.source.cacheTo).toStrictEqual({ + type: 'inline', + }); + }); + + test('manifest does not contain options when not specified', () => { + // GIVEN + const app = new App(); + const stack = new Stack(app); + const asset = new DockerImageAsset(stack, 'DockerImage6', { + directory: path.join(__dirname, 'demo-image'), + }); + + // WHEN + const asm = app.synth(); + + // THEN + const manifestArtifact = getAssetManifest(asm); + const manifest = readAssetManifest(manifestArtifact); + expect(Object.keys(manifest.dockerImages ?? {}).length).toBe(1); + expect(manifest.dockerImages?.[asset.assetHash]?.source.cacheFrom).toBeUndefined(); + expect(manifest.dockerImages?.[asset.assetHash]?.source.cacheTo).toBeUndefined(); + }); +}); + +function isAssetManifest(x: CloudArtifact): x is AssetManifestArtifact { + return x instanceof AssetManifestArtifact; +} + +function getAssetManifest(asm: CloudAssembly): AssetManifestArtifact { + const manifestArtifact = asm.artifacts.filter(isAssetManifest)[0]; + if (!manifestArtifact) { + throw new Error('no asset manifest in assembly'); + } + return manifestArtifact; +} + +function readAssetManifest(manifestArtifact: AssetManifestArtifact): AssetManifest { + return JSON.parse(fs.readFileSync(manifestArtifact.file, { encoding: 'utf-8' })); +} diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/integ-assets-docker.template.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/integ-assets-docker.template.json index 8c7c033450117..ac306d4d02d70 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/integ-assets-docker.template.json +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/integ-assets-docker.template.json @@ -81,6 +81,11 @@ "Value": { "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:60dea2e16e94d1977b92fe03fa7085fea446233f1fe499702b69593438baa59f" } + }, + "ImageUri6": { + "Value": { + "Fn::Sub": "${AWS::AccountId}.dkr.ecr.${AWS::Region}.${AWS::URLSuffix}/cdk-hnb659fds-container-assets-${AWS::AccountId}-${AWS::Region}:0a3355be12051c9984bf2b0b2bba4e6ea535968e5b6e7396449701732fe5ed14" + } } }, "Parameters": { diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/tree.json b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/tree.json index 32988bdc52723..06c8f34bf353e 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/tree.json +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.js.snapshot/tree.json @@ -262,8 +262,8 @@ "version": "0.0.0" } }, - "ImageUri5": { - "id": "ImageUri5", + "ImageUri4": { + "id": "ImageUri4", "path": "integ-assets-docker/ImageUri5", "constructInfo": { "fqn": "@aws-cdk/core.CfnOutput", diff --git a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.ts b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.ts index 702b83fe011a5..65a6f266d5a35 100644 --- a/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.ts +++ b/packages/@aws-cdk/aws-ecr-assets/test/integ.assets-docker.ts @@ -31,17 +31,24 @@ const asset5 = new assets.DockerImageAsset(stack, 'DockerImage5', { }, }); +const asset6 = new assets.DockerImageAsset(stack, 'DockerImage6', { + directory: path.join(__dirname, 'demo-image'), + cacheTo: { type: 'inline' }, +}); + const user = new iam.User(stack, 'MyUser'); asset.repository.grantPull(user); asset2.repository.grantPull(user); asset3.repository.grantPull(user); asset4.repository.grantPull(user); asset5.repository.grantPull(user); +asset6.repository.grantPull(user); new cdk.CfnOutput(stack, 'ImageUri', { value: asset.imageUri }); new cdk.CfnOutput(stack, 'ImageUri2', { value: asset2.imageUri }); new cdk.CfnOutput(stack, 'ImageUri3', { value: asset3.imageUri }); new cdk.CfnOutput(stack, 'ImageUri4', { value: asset4.imageUri }); new cdk.CfnOutput(stack, 'ImageUri5', { value: asset5.imageUri }); +new cdk.CfnOutput(stack, 'ImageUri6', { value: asset6.imageUri }); app.synth(); diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/assets/docker-image-asset.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/assets/docker-image-asset.ts index 809ef1c9f91f4..6224af4fb6c77 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/assets/docker-image-asset.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/assets/docker-image-asset.ts @@ -97,6 +97,22 @@ export interface DockerImageSource { * @see https://docs.docker.com/engine/reference/commandline/build/#custom-build-outputs */ readonly dockerOutputs?: string[]; + + /** + * Cache from options to pass to the `docker build` command. + * + * @default - no cache from options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheFrom?: DockerCacheOption[]; + + /** + * Cache to options to pass to the `docker build` command. + * + * @default - no cache to options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheTo?: DockerCacheOption; } /** @@ -113,3 +129,25 @@ export interface DockerImageDestination extends AwsDestination { */ readonly imageTag: string; } + +/** + * Options for configuring the Docker cache backend + */ +export interface DockerCacheOption { + /** + * The type of cache to use. + * Refer to https://docs.docker.com/build/cache/backends/ for full list of backends. + * @default - unspecified + * + * @example 'registry' + */ + readonly type: string; + /** + * Any parameters to pass into the docker cache backend configuration. + * Refer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. + * @default {} No options provided + * + * @example { ref: `12345678.dkr.ecr.us-west-2.amazonaws.com/cache:${branch}`, mode: "max" } + */ + readonly params?: { [key: string]: string }; +} \ No newline at end of file diff --git a/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/metadata-schema.ts b/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/metadata-schema.ts index c3d4ac127a46f..bcc67298ff308 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/metadata-schema.ts +++ b/packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/metadata-schema.ts @@ -71,6 +71,28 @@ export interface Tag { readonly value: string } +/** + * Options for configuring the Docker cache backend + */ +export interface ContainerImageAssetCacheOption { + /** + * The type of cache to use. + * Refer to https://docs.docker.com/build/cache/backends/ for full list of backends. + * @default - unspecified + * + * @example 'registry' + */ + readonly type: string; + /** + * Any parameters to pass into the docker cache backend configuration. + * Refer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. + * @default {} No options provided + * + * @example { ref: `12345678.dkr.ecr.us-west-2.amazonaws.com/cache:${branch}`, mode: "max" } + */ + readonly params?: { [key: string]: string }; +} + /** * Metadata Entry spec for container images. */ @@ -160,6 +182,22 @@ export interface ContainerImageAssetMetadataEntry extends BaseAssetMetadataEntry * @see https://docs.docker.com/engine/reference/commandline/build/#custom-build-outputs */ readonly outputs?: string[]; + + /** + * Cache from options to pass to the `docker build` command. + * + * @default - no cache from options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheFrom?: ContainerImageAssetCacheOption[]; + + /** + * Cache to options to pass to the `docker build` command. + * + * @default - no cache to options are passed to the build command + * @see https://docs.docker.com/build/cache/backends/ + */ + readonly cacheTo?: ContainerImageAssetCacheOption; } /** diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/assets.schema.json b/packages/@aws-cdk/cloud-assembly-schema/schema/assets.schema.json index 28dea7efbf357..6e7f02037f744 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/assets.schema.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/assets.schema.json @@ -176,9 +176,40 @@ "items": { "type": "string" } + }, + "cacheFrom": { + "description": "Cache from options to pass to the `docker build` command. (Default - no cache from options are passed to the build command)", + "type": "array", + "items": { + "$ref": "#/definitions/DockerCacheOption" + } + }, + "cacheTo": { + "description": "Cache to options to pass to the `docker build` command. (Default - no cache to options are passed to the build command)", + "$ref": "#/definitions/DockerCacheOption" } } }, + "DockerCacheOption": { + "description": "Options for configuring the Docker cache backend", + "type": "object", + "properties": { + "type": { + "description": "The type of cache to use.\nRefer to https://docs.docker.com/build/cache/backends/ for full list of backends. (Default - unspecified)", + "type": "string" + }, + "params": { + "description": "Any parameters to pass into the docker cache backend configuration.\nRefer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. (Default {} No options provided)", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "type" + ] + }, "DockerImageDestination": { "description": "Where to publish docker images", "type": "object", diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json index 92eb946bc9149..12d263bfdea2f 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json @@ -248,6 +248,17 @@ "type": "string" } }, + "cacheFrom": { + "description": "Cache from options to pass to the `docker build` command. (Default - no cache from options are passed to the build command)", + "type": "array", + "items": { + "$ref": "#/definitions/ContainerImageAssetCacheOption" + } + }, + "cacheTo": { + "description": "Cache to options to pass to the `docker build` command. (Default - no cache to options are passed to the build command)", + "$ref": "#/definitions/ContainerImageAssetCacheOption" + }, "id": { "description": "Logical identifier for the asset", "type": "string" @@ -268,6 +279,26 @@ "sourceHash" ] }, + "ContainerImageAssetCacheOption": { + "description": "Options for configuring the Docker cache backend", + "type": "object", + "properties": { + "type": { + "description": "The type of cache to use.\nRefer to https://docs.docker.com/build/cache/backends/ for full list of backends. (Default - unspecified)", + "type": "string" + }, + "params": { + "description": "Any parameters to pass into the docker cache backend configuration.\nRefer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. (Default {} No options provided)", + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "type" + ] + }, "Tag": { "description": "Metadata Entry spec for stack tag.", "type": "object", diff --git a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json index 7233abc4c3527..0d5aff521d3a2 100644 --- a/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json +++ b/packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.version.json @@ -1,3 +1 @@ -{ - "version": "30.1.0" -} +{"version":"31.0.0"} diff --git a/packages/@aws-cdk/core/lib/assets.ts b/packages/@aws-cdk/core/lib/assets.ts index 10e1a61e7e5d0..72f9429f2afdb 100644 --- a/packages/@aws-cdk/core/lib/assets.ts +++ b/packages/@aws-cdk/core/lib/assets.ts @@ -242,6 +242,18 @@ export interface DockerImageAssetSource { */ readonly dockerOutputs?: string[]; + /** + * Cache from options to pass to the `docker build` command. + * @default - no cache from args are passed + */ + readonly dockerCacheFrom?: DockerCacheOption[]; + + /** + * Cache to options to pass to the `docker build` command. + * @default - no cache to args are passed + */ + readonly dockerCacheTo?: DockerCacheOption; + } /** @@ -347,3 +359,25 @@ export interface DockerImageAssetLocation { */ readonly imageTag?: string; } + +/** + * Options for configuring the Docker cache backend + */ +export interface DockerCacheOption { + /** + * The type of cache to use. + * Refer to https://docs.docker.com/build/cache/backends/ for full list of backends. + * @default - unspecified + * + * @example 'registry' + */ + readonly type: string; + /** + * Any parameters to pass into the docker cache backend configuration. + * Refer to https://docs.docker.com/build/cache/backends/ for cache backend configuration. + * @default {} No options provided + * + * @example { ref: `12345678.dkr.ecr.us-west-2.amazonaws.com/cache:${branch}`, mode: "max" } + */ + readonly params?: { [key: string]: string }; +} \ No newline at end of file diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts index 0f923dfaef659..109ddc4c00c1f 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/asset-manifest-builder.ts @@ -71,6 +71,8 @@ export class AssetManifestBuilder { networkMode: asset.networkMode, platform: asset.platform, dockerOutputs: asset.dockerOutputs, + cacheFrom: asset.dockerCacheFrom, + cacheTo: asset.dockerCacheTo, }, { repositoryName: target.repositoryName, imageTag, diff --git a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts index bce9dac8ced65..70dc22333bf84 100644 --- a/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts +++ b/packages/@aws-cdk/core/lib/stack-synthesizers/legacy.ts @@ -148,6 +148,8 @@ export class LegacyStackSynthesizer extends StackSynthesizer implements IReusabl networkMode: asset.networkMode, platform: asset.platform, outputs: asset.dockerOutputs, + cacheFrom: asset.dockerCacheFrom, + cacheTo: asset.dockerCacheTo, }; this.boundStack.node.addMetadata(cxschema.ArtifactMetadataEntryType.ASSET, metadata); diff --git a/packages/@aws-cdk/cx-api/lib/assets.ts b/packages/@aws-cdk/cx-api/lib/assets.ts index 3cc8312f646d4..42461895828be 100644 --- a/packages/@aws-cdk/cx-api/lib/assets.ts +++ b/packages/@aws-cdk/cx-api/lib/assets.ts @@ -17,6 +17,8 @@ export const ASSET_RESOURCE_METADATA_DOCKER_BUILD_TARGET_KEY = 'aws:asset:docker export const ASSET_RESOURCE_METADATA_PROPERTY_KEY = 'aws:asset:property'; export const ASSET_RESOURCE_METADATA_IS_BUNDLED_KEY = 'aws:asset:is-bundled'; export const ASSET_RESOURCE_METADATA_DOCKER_OUTPUTS_KEY = 'aws:asset:docker-outputs'; +export const ASSET_RESOURCE_METADATA_DOCKER_CACHE_FROM_KEY = 'aws:asset:docker-cache-from'; +export const ASSET_RESOURCE_METADATA_DOCKER_CACHE_TO_KEY = 'aws:asset:docker-cache-to'; /** * Separator string that separates the prefix separator from the object key separator. diff --git a/packages/cdk-assets/lib/private/docker.ts b/packages/cdk-assets/lib/private/docker.ts index 509e15cbed22f..f5a6d675aa634 100644 --- a/packages/cdk-assets/lib/private/docker.ts +++ b/packages/cdk-assets/lib/private/docker.ts @@ -19,6 +19,8 @@ interface BuildOptions { readonly networkMode?: string; readonly platform?: string; readonly outputs?: string[]; + readonly cacheFrom?: DockerCacheOption[]; + readonly cacheTo?: DockerCacheOption; } export interface DockerCredentialsConfig { @@ -36,6 +38,11 @@ enum InspectImageErrorCode { Podman = 125 } +export interface DockerCacheOption { + readonly type: string; + readonly params?: { [key: string]: string }; +} + export class Docker { private configDir: string | undefined = undefined; @@ -90,6 +97,8 @@ export class Docker { ...options.networkMode ? ['--network', options.networkMode] : [], ...options.platform ? ['--platform', options.platform] : [], ...options.outputs ? options.outputs.map(output => [`--output=${output}`]) : [], + ...options.cacheFrom ? options.cacheFrom.map(cacheFrom => this.cacheOptionToFlag(cacheFrom)) : [], + ...options.cacheTo ? [this.cacheOptionToFlag(options.cacheTo)] : [], '.', ]; await this.execute(buildCommand, { cwd: options.directory }); @@ -179,6 +188,14 @@ export class Docker { throw e; } } + + private cacheOptionToFlag(option: DockerCacheOption): string { + let flag = `type=${option.type}`; + if (option.params) { + flag += ',' + Object.entries(option.params).map(([k, v]) => `${k}=${v}`).join(','); + } + return flag; + } } export interface DockerFactoryOptions { diff --git a/packages/cdk-assets/lib/private/handlers/container-images.ts b/packages/cdk-assets/lib/private/handlers/container-images.ts index 811d02e1a8d01..e25b12d368a01 100644 --- a/packages/cdk-assets/lib/private/handlers/container-images.ts +++ b/packages/cdk-assets/lib/private/handlers/container-images.ts @@ -173,6 +173,8 @@ class ContainerImageBuilder { networkMode: source.networkMode, platform: source.platform, outputs: source.dockerOutputs, + cacheFrom: source.cacheFrom, + cacheTo: source.cacheTo, }); }