'How to customize docker build context when deploy a dockized .NET6 lambda using AWS cdk?

I am trying to deploy a dockized.NET Lambda application using the Code.fromAssetImage method from AWS CDK.

My folder structure looks like this

Lambda.Lab - root folder

  • Lambda.App - folder contains csprojects
    • AWSLambda1 - .NET6 AWS Lambda Project
      • Dockerfile
    • AWSLambda1.Data - .NET6 class library project
  • Infra - folder contains cdk project
    • lib
      • infra-stack.ts - stack file

I tested building the Dockerfile by running the command below under the AWSLambda1 project folder successfully. Note that I am using .. at the end of the command to move the build context up from where the Dockerfile is, in order to get access to the dependent class library AWSLambda1.Data

docker build -t AWSLambda1 ..

Docker file

FROM public.ecr.aws/lambda/dotnet:6 AS base

FROM mcr.microsoft.com/dotnet/sdk:6.0-bullseye-slim as build
WORKDIR /src
COPY ["AWSLambda1/AWSLambda1.csproj", "AWSLambda1/"]
COPY ["AWSLambda1.Data/AWSLambda1.Data.csproj", "AWSLambda1.Data/"]
RUN dotnet restore "AWSLambda1/AWSLambda1.csproj"

#WORKDIR "/src/AWSLambda1"
COPY . .
RUN dotnet build "AWSLambda1/AWSLambda1.csproj" --configuration Release --output /app/build
# --configuration Release --output /app/build

FROM build AS publish
RUN dotnet publish "AWSLambda1/AWSLambda1.csproj" \
            --configuration Release \ 
            --runtime linux-x64 \
            --self-contained false \ 
            --output /app/publish \
            -p:PublishReadyToRun=true  

FROM base AS final
WORKDIR /var/task
COPY --from=publish /app/publish .
CMD ["AWSLambda1::AWSLambda1.Function::FunctionHandler"]

So my question is how can deploy the same thing using AWS CDK? I can see the two problems need to be addressed

  1. make sure both AWSLambda1 and AWSLambda1 are captured by the CDK project
  2. make sure the build context is set to one level up from the AWSLambda1 project

Below is my infra-stack.ts with all my attempts to solve the problem but with no luck so far.

import { Stack, StackProps, Duration, CfnOutput } from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';
import { Code, Handler } from 'aws-cdk-lib/aws-lambda';

export class InfraStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const fn = new lambda.Function(this, 'lambda-docker-attempt1', {
      runtime: lambda.Runtime.FROM_IMAGE,
      handler: Handler.FROM_IMAGE,

      //attempt 1
      //code: Code.fromAssetImage(path.join(__dirname,'../../lambda.app/AWSLambda1')),
      //[100%] fail: docker build --tag cdkasset-b0efaad78ead998b80e6ab6595a21d7fe24c06ec70f65d4e9005540eabf13161 . 
      //exited with error code 1: COPY failed: file not found in build context or excluded by .dockerignore: stat AWSLambda1/AWSLambda1.csproj: file does not exist

      //attempt 2
      // code: Code.fromAssetImage(path.join(__dirname,'../../lambda.app/'),{
      //   file: '/AWSLambda1/Dockerfile',
      // }),
      //[100%] fail: docker build --tag cdkasset-1005a75db171185bca51ea88ef8b74313d444af0d936e946ebe7493d684ab9dc --file /AWSLambda1/Dockerfile . 
      //exited with error code 1: unable to prepare context: unable to evaluate symlinks in Dockerfile path: CreateFile C:\AWSLambda1: The system cannot find the file specified.

      //attempt 3
      code: Code.fromAssetImage(path.join(__dirname,'../../'),{
        file: '/lambda.app/AWSLambda1/Dockerfile',
      }),
      //[100%] fail: docker build --tag cdkasset-1005a75db171185bca51ea88ef8b74313d444af0d936e946ebe7493d684ab9dc --file /AWSLambda1/Dockerfile . 
      //exited with error code 1: unable to prepare context: unable to evaluate symlinks in Dockerfile path: CreateFile C:\AWSLambda1: The system cannot find the file specified.

      timeout: Duration.seconds(30),
    });
  }
}

I found an old discussion about DockerImageAsset which seems to similar to my problem, but mine is for lambda deployment only.

I am new to AWS CDK, not sure if what I am looking for is possible or now. Any suggestions are very appreciated. Thanks a lot in advance!!!



Solution 1:[1]

Thanks to my lovely colleague Alex, it turns 'attempt 2' was the closest answer with a minor change to remove the front '/' for file path, which then becomes the actual answer. A complete answer is attached below. Hope this can help with anyone who has the same issue.

import { Stack, StackProps, Duration } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';
import { Code, Handler } from 'aws-cdk-lib/aws-lambda';

export class InfraStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const fn = new lambda.Function(this, 'lambda-docker-attempt1', {
      runtime: lambda.Runtime.FROM_IMAGE,
      handler: Handler.FROM_IMAGE,
      code: Code.fromAssetImage(path.join(__dirname,'../../lambda.app/'),{
        file: 'AWSLambda1/Dockerfile',
      }),
      timeout: Duration.seconds(30),
    });
  }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Wjun