title: How to deploy AWS Lambdas with Docker and CDK?
body: <h3>Context</h3>
  <p>I'm able to deploy to AWS lambda using Docker and CDK.</p>
  <p>Here is what I did:</p>
  <p>I have a Java package <code>TestLambda</code>. I use <code>docker build -t test-lambda .</code> there to build the docker image.</p>
  <pre><code>FROM public.ecr.aws/lambda/java:11
  
  # /var/task should only contains *.class files
  #COPY build/classes/java/main ${LAMBDA_TASK_ROOT}
  
  # Always use /var/task/lib for dependencies
  COPY build/dependency/* ${LAMBDA_TASK_ROOT}/lib/
  
  COPY src/main/resources/log4j2.xml ${LAMBDA_TASK_ROOT}
  
  ARG jarFile=TestLambda-0.0.1.jar
  
  # Looks
  COPY build/libs/${jarFile} ${LAMBDA_TASK_ROOT}/lib/
  
  RUN cd ${LAMBDA_TASK_ROOT} &amp;&amp; jar -xf ${LAMBDA_TASK_ROOT}/lib/${jarFile}
  
  # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
  CMD [ &quot;com.mywebsite.TestLambda::handle&quot; ]
  
  </code></pre>
  <p>I have a CDK package where I defined Lambda Stack:</p>
  <pre class="lang-js prettyprint-override"><code>export interface LambdaStackProps extends cdk.StackProps {
    readonly env : cdk.Environment
  }
  
  export class LambdaStack extends cdk.Stack {
  
    // Make it public so that can be binded to Api Gateway
    public readonly testLambda : lambda.Function;
  
    constructor(scope: cdk.App, id: string, props: LambdaStackProps) {
        super(scope, id, props);
  
        this.testLambda = this.createLambda();
    }
  
  
    private createLambda() {
        // Configure path to Dockerfile
        const dockerfile = path.join(__dirname, &quot;../../TestLambda/&quot;);
  
        // Because here it uses Asset,
        // need run cdk bootstrap aws://&lt;AwsAccountId&gt;/us-east-1
        return new lambda.DockerImageFunction(this, 'TestLambdaHandler', {
            functionName: 'TestLambdaHandler',
            description: 'Lambda that render presigned url for S3 bucket.',
            code: lambda.DockerImageCode.fromImageAsset(dockerfile),
            timeout: cdk.Duration.minutes(2),
            memorySize: 512,
            role: this.createLambdaExecutionRole(),
            tracing: lambda.Tracing.ACTIVE,
        });
    }
  
    private createLambdaExecutionRole() {
      return new iam.Role(this, &quot;TestLambdaHandlerRole&quot;, {
        description: &quot;Execution role for TestLambdaHandler.&quot;,
        assumedBy: new iam.ServicePrincipal(&quot;lambda.amazonaws.com&quot;),
        inlinePolicies: {
          &quot;TestLambdaHandlerRoleInlinePolicies&quot; : new iam.PolicyDocument(
            {
              statements : [
                new iam.PolicyStatement({
                  effect: iam.Effect.ALLOW,
                  resources: [&quot;*&quot;],
                  actions: [
                    &quot;s3:Create*&quot;,
                    &quot;s3:List*&quot;,
                    &quot;s3:Set*&quot;,
                    &quot;s3:Put*&quot;,
                    &quot;s3:Get*&quot;,
                  ]
                }),
                new iam.PolicyStatement({
                  effect: iam.Effect.ALLOW,
                  resources: [&quot;*&quot;],
                  actions: [
                    &quot;logs:Get*&quot;, &quot;logs:Describe*&quot;, &quot;logs:Create*&quot;, &quot;logs:Put*&quot;
                  ]
                })
              ]
            }
          )
        }
      });
    }
  }
  </code></pre>
  <p>With the above code, I'm able to upload the docker image and deploy to AWS Lambda with command<code>cdk deploy LambdaStack</code>.</p>
  <h3>My question</h3>
  <p>Above code works for one Java Lambda function. And now I want add more Java functions to my Java package, and use the CDK package to deploy the docker image as a whole.</p>
  <p>How can I do that?</p>
  <p>As you can see in my Dockerfile, there is a line <code>CMD [ &quot;com.mywebsite.TestLambda::handle&quot; ]</code> specified the function that should be run, and Dockerfile can only have one CMD.</p>
  <p>I tried to add another CMD for my new function and make the Dockerfile looks like:</p>
  <pre><code>CMD [ &quot;com.mywebsite.GetS3PresignedUrl::handleRequest&quot; ]
  CMD [ &quot;com.mywebsite.activity.Test::handleRequest&quot; ]
  </code></pre>
  <p>Of course, I also updated the TypeScript CDK package to add corresponding code for the second lambda function. Basically a copy of my above code.</p>
  <p>After deployment, I see two AWS lambda functions. But both lambda functions call <code>com.mywebsite.activity.Test::handleRequest</code>. As mentioned <a href="https://docs.docker.com/engine/reference/builder/" rel="nofollow noreferrer">here</a>, &quot;If you list more than one <code>CMD</code> then only the last <code>CMD</code> will take effect.&quot;</p>
  <p>I want the single docker image to hold all my Lambda functions, how can I do that?</p>
  <h3>Update 2021-11-22</h3>
  <p>With @gshpychka's help, I'm able to get this working.</p>
  <p>Paste the CDK code for one lambda here. Other lambda configurations should be the same.</p>
  <pre class="lang-js prettyprint-override"><code>private createTestLambda() {
        const dockerfile = path.join(__dirname, &quot;../../MyLambda/&quot;);
        const myCode = lambda.Code.fromAssetImage(dockerfile, {
          cmd: ['com.mywebsite.TestActivityWrapper::handleRequest'],
        });
        return new lambda.Function(this, 'TestLambda', {
            functionName: 'TestLambda',
            description: 'Test lambda',
            code: myCode,
            handler: lambda.Handler.FROM_IMAGE,
            runtime: lambda.Runtime.FROM_IMAGE,
            timeout: cdk.Duration.minutes(2),
            memorySize: 512,
            role: this.createTestLambdaExecutionRole(),
            tracing: lambda.Tracing.ACTIVE,
        });
    }
  
    private createTestLambdaExecutionRole() {
      return new iam.Role(this, &quot;TestLambdaRole&quot;, {
        description: &quot;Execution role for TestLambdaRole.&quot;,
        assumedBy: new iam.ServicePrincipal(&quot;lambda.amazonaws.com&quot;),
        inlinePolicies: {
          &quot;TestLambdaRoleRoleInlinePolicies&quot; : new iam.PolicyDocument(
            {
              statements : [
                new iam.PolicyStatement({
                  effect: iam.Effect.ALLOW,
                  resources: [&quot;*&quot;],
                  actions: [
                    &quot;s3:Create*&quot;,
                    &quot;s3:List*&quot;,
                    &quot;s3:Set*&quot;,
                    &quot;s3:Put*&quot;,
                    &quot;s3:Get*&quot;,
                  ]
                }),
                new iam.PolicyStatement({
                  effect: iam.Effect.ALLOW,
                  resources: [&quot;*&quot;],
                  actions: [
                    &quot;logs:Get*&quot;, &quot;logs:Describe*&quot;, &quot;logs:Create*&quot;, &quot;logs:Put*&quot;
                  ]
                })
              ]
            }
          )
        }
      });
    }
  </code></pre>