I ended up using a Docker container to install the aws-cdk module into a specific path, then zip up the container and copying it to a bind-mounted directory so that it is available on the underlying host.
I built the project using Gradle and the gradle-docker-plugin by Ben Muschko. I have not spent time trying to use a smaller Node image to speed up builds.
task createCdkDockerfile(type: Dockerfile) {
from 'node:latest'
defaultCommand('/bin/bash', '-c', "apt-get update && apt-get install -y zip && mkdir -p /nodejs && npm config set prefix /nodejs/bin && npm install -g aws-cdk && pushd /nodejs/bin && zip -r --symlinks /opt/aws-cdk.zip *")
}
task buildCdkImage(type:DockerBuildImage) {
dependsOn createCdkDockerfile
images.add('my-aws-cdk:latest')
}
ext.maybeConvertWindowsPath = { path ->
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
path = "/${path.replace("\\", "/").replace(":", "")}"
}
return path
}
task createCdkContainer(type: DockerCreateContainer) {
def dockerBindDir = new File(buildDir, "docker")
dockerBindDir.mkdirs()
dependsOn buildCdkImage
targetImageId buildCdkImage.getImageId()
hostConfig.autoRemove = true
hostConfig.binds = ["${maybeConvertWindowsPath(buildDir.toString())}/docker" : "/opt"]
}
task startCdkContainer(type: DockerStartContainer) {
dependsOn createCdkContainer
targetContainerId createCdkContainer.getContainerId()
}
task waitCdkContainer(type: DockerWaitContainer) {
dependsOn startCdkContainer
targetContainerId createCdkContainer.getContainerId()
}
The zip file is available at ${buildDir}/docker/aws-cdk.zip.
Adding the CDK as a layer is as per the Nodejs example in my question, so something like this:
LayerVersion nodeLayer = LayerVersion.Builder.create(this, "aws-cdk-layer")
.description("Layer containing AWS CDK")
.code(
Code.fromAsset(somePathTo-aws-cdk.zip)
)
.build();
Points to watch out for:
- if building on Windows, zipping up on Windows then unzipping on Linux will give issues with files that should be executable no longer being executable, i.e.
cdk itself.
- bind mounting directories seems to have issues when on Windows, hence the need to sanitize the filename.
- when zipping, it's important to use the
--symlinks option, otherwise the cdk executable will not be able to find the cdk.js file.
I would have preferred using tar to zip the file up, but fromAsset() won't accept tar files.