この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、NodejsFunctionクラスで共通で行いたい設定(bundling.forceDockerBundlingなど)を、カスタムConstructクラスを作って省略してみました。
NodejsFunctionのローカルビルドに必要な対応
MacOS上でNodejsFunctionクラスのConstructを含むAWS CDK Stackをローカルビルドする際には、次のいずれかの対応が必要です。
- Docker Desktopが起動していること
esbuild
がインスールされており、NodejsFunction
のbundling.forceDockerBundling
propがfalse
に設定されていること
上記対応がなされていない場合、CDKビルドがエラーとなります。
$ cdk synth
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
ERRO[0000] Can't add file /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws_cdk_app/node_modules/aws-cdk-lib/aws-lambda-nodejs/lib/bundling.js.map to tar: io: read/write on closed pipe
ERRO[0000] Can't close tar writer: io: read/write on closed pipe
関数ごとにbundling.forceDockerBundling設定するのは冗長
前述の2.方法で対応する前提とした場合、作成する全てまたはほとんどのLambda関数に共通でbundling.forceDockerBundling
を設定する必要があるのですが、関数の数が増えてくると冗長になってきます。
lib/aws_cdk_app-stack.ts
//(省略なし)
import { Construct } from 'constructs';
import { Stack, StackProps, aws_lambda_nodejs } from 'aws-cdk-lib';
export class AwsCdkAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
new aws_lambda_nodejs.NodejsFunction(this, 'HelloWorld1', {
entry: 'src/lambda/handlers/hello-world-handler.ts',
bundling: {
forceDockerBundling: false,
},
});
new aws_lambda_nodejs.NodejsFunction(this, 'HelloWorld2', {
entry: 'src/lambda/handlers/hello-world-handler.ts',
bundling: {
forceDockerBundling: false,
},
});
new aws_lambda_nodejs.NodejsFunction(this, 'HelloWorld3', {
entry: 'src/lambda/handlers/hello-world-handler.ts',
bundling: {
forceDockerBundling: false,
},
});
new aws_lambda_nodejs.NodejsFunction(this, 'HelloWorld4', {
entry: 'src/lambda/handlers/hello-world-handler.ts',
bundling: {
forceDockerBundling: false,
},
});
new aws_lambda_nodejs.NodejsFunction(this, 'HelloWorld5', {
entry: 'src/lambda/handlers/hello-world-handler.ts',
bundling: {
forceDockerBundling: false,
},
});
//and more...
}
}
カスタムConstructクラスで省略してみる
そこでbundling.forceDockerBundling
の設定を、カスタムConstructクラスを使用して省略してみます。
まずカスタムConstructクラスを別ファイルで作成します。NodejsFunction
のbundling.forceDockerBundling
が既定でfalse
となるようにし、またentry
は格納パスがsrc/lambda/handlers/
で固定であると想定し、ファイル名のみを指定すれば良いようにしています。
lib/custom-construct-class.ts
//カスタムConstructクラス
import { Construct } from 'constructs';
import { aws_lambda_nodejs } from 'aws-cdk-lib';
export interface AwsCdkNodejsLambdaHandlerProps {
handlerFile: string;
}
export class AwsCdkNodejsLambdaHandler extends Construct {
public readonly queueArn: string;
constructor(
scope: Construct,
id: string,
props: AwsCdkNodejsLambdaHandlerProps
) {
super(scope, id);
new aws_lambda_nodejs.NodejsFunction(this, 'AwsCdkNodejsLambdaHandler', {
entry: `src/lambda/handlers/${props.handlerFile}.ts`,
bundling: {
forceDockerBundling: false,
},
});
}
}
作成したカスタムConstructクラスを使用してLambda関数を定義します。
lib/aws_cdk_app-stack.ts
//(省略あり)
import { Construct } from 'constructs';
import { Stack, StackProps } from 'aws-cdk-lib';
import { AwsCdkNodejsLambdaHandler } from './custom-construct-class';
export class AwsCdkAppStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props);
new AwsCdkNodejsLambdaHandler(this, 'HelloWorld1', {
handlerFile: 'hello-world-handler',
});
new AwsCdkNodejsLambdaHandler(this, 'HelloWorld2', {
handlerFile: 'hello-world-handler',
});
new AwsCdkNodejsLambdaHandler(this, 'HelloWorld3', {
handlerFile: 'hello-world-handler',
});
new AwsCdkNodejsLambdaHandler(this, 'HelloWorld4', {
handlerFile: 'hello-world-handler',
});
new AwsCdkNodejsLambdaHandler(this, 'HelloWorld5', {
handlerFile: 'hello-world-handler',
});
//and more...
}
}
ビルドを行うとエラー無く実行されました。
$ cdk synth
Bundling asset AwsCdkAppStack/HelloWorld1/AwsCdkNodejsLambdaHandler/Code/Stage...
cdk.out/bundling-temp-e3d6ffa14aa789fb0ae3789c57f95d9554e8d404e91655d711e4df0617e9c42c/index.js 188b
⚡ Done in 3ms
Resources:
HelloWorld1AwsCdkNodejsLambdaHandlerServiceRoleDBC2ED23:
...
おわりに
NodejsFunctionで共通で行いたい設定(bundling.forceDockerBundlingなど)をカスタムConstructクラスで省略してみました。
そもそも今までbundling.forceDockerBundling
の設定を知らず、NodejsFunction
を作成する開発の際にはデスクトップで必ずDockerを起動するようにしていたのですが、今後はしなくて良くなりました。
参考
- AWS CDK でカスタム Construct を作って、他の CDK プロジェクトから使ってみる | DevelopersIO
- [AWS-CDK] NodejsFunction の snapshot test がCI環境で落ちる
- aws-cdk-lib.aws_lambda_nodejs module · AWS CDK
以上