问题
What is the best way to bundle up the AWS CDK as a Lambda layer please?
I need to call the CDK from a Java process, so wish to use the Java 11 runtime and then install Nodejs and the CDK as 2 separate layers. Currently I download the Nodejs binaries and then use something like the following:
LayerVersion nodeLayer = LayerVersion.Builder.create(this, "node-layer")
.description("Layer containing Node.js")
.code(
Code.fromAsset(somePathToNodejs)
)
.build();
then refer to the layer within the Lambda constructor / builder.
The CDK is installed as npm install -g aws-cdk
, so I don't know how best to bundle this up in a similar fashion.
回答1:
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 thecdk
executable will not be able to find thecdk.js
file.
I would have preferred using tar
to zip the file up, but fromAsset()
wont accept tar files.
来源:https://stackoverflow.com/questions/60379916/how-to-package-aws-cdk-into-lambda-layer