aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.5k stars 1.17k forks source link

Bug: sam fails to build subdirectory based Dockerfile images on Windows #5345

Closed kurt-hectic closed 1 year ago

kurt-hectic commented 1 year ago

Description:

sam build fails to build images of which the Dockerfile is located in a sub-directory of the directory containing the assets, when using cdk on Windows and fromImageAsset to construct a docker based lambda function. Such configuration is sometimes needed to share code between docker images. The image is built correctly when running cdk deploy, but not when I would like to build docker images using sam build for local testing with sam local invoke. Here is an example:

const lambdaFunction = new lambda.DockerImageFunction(this, "TestLambdaFunction", {
      functionName: "TestLambdaFunction",
      code: lambda.DockerImageCode.fromImageAsset("./docker/", {
          file: "myimage/Dockerfile",
       } )
    });
project root
├── docker           # basedirectory for docker files of lambda functions
│   ├── myimage      # asset direcotry
│        │  Dockerfile    # Dockerfile
│        │  app.py
│   ├── mylib             # shared libs 
│        │  mylib.py      # library 

The issue is likely related to Windows, as the docker images of the demo project are built correctly on Linux. A possible reason could be that aws:asset:dockerfile-path in build.toml contains an unix-style path:

[function_build_definitions.92b0d2cc-b348-4682-941e-2ab406765397.metadata]
"aws:cdk:path" = "TestcdkStack/TestLambdaFunction/Resource"
"aws:asset:path" = "asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123"
"aws:asset:dockerfile-path" = "myimage/Dockerfile"
"aws:asset:property" = "Code.ImageUri"
Dockerfile = "myimage\\Dockerfile"
DockerContext = "C:\\Users\\Timo\\Documents\\git\\testcdk\\cdk.out\\asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123"

However, using a windows-style path (myimage\\Dockerfile) as file parameter for fromImageAsset does not solve the problem.

The issue is related but not identical to https://github.com/aws/aws-sam-cli/pull/4074, https://github.com/aws/aws-cdk/issues/3342 and https://github.com/aws/aws-sam-cli/issues/4059.

Steps to reproduce:

Observed result:

C:\Users\Timo\Documents\git\testcdk> sam local invoke -t cdk.out\TestcdkStack.template.json --debug

2023-06-12 20:46:14,681 | Local image was not found. 2023-06-12 20:46:14,682 | Removing rapid images for repo testlambdafunctionc089708a Building image...... 2023-06-12 20:46:17,962 | Failed to build Docker Image NoneType: None

C:\Users\Timo\Documents\git\testcdk> sam build -t cdk.out\TestcdkStack.template.json --debug   (ran before sam local invoke)

2023-06-12 20:42:46,106 | Found Lambda function with name='TestLambdaFunctionC089708A' and Imageuri='testlambdafunctionc089708a' 2023-06-12 20:42:46,112 | Error occurred while trying to track an event: Event 'BuildFunctionRuntime' does not accept value 'None'. 2023-06-12 20:42:46,116 | Instantiating build definitions 2023-06-12 20:42:46,146 | Unique function build definition found, adding as new (Function Build Definition: BuildDefinition(None, C:\Users\Timo\Documents\git\testcdk\cdk.out, Image, , eacc9958-29f8-4c8c-8ed2-9fb9e9aae05e, {'aws:cdk:path': 'TestcdkStack/TestLambdaFunction/Resource', 'aws:asset:path': 'asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'aws:asset:dockerfile-path': 'myimage/Dockerfile', 'aws:asset:property': 'Code.ImageUri', 'Dockerfile': 'myimage\Dockerfile', 'DockerContext': 'C:\Users\Timo\Documents\git\testcdk\cdk.out\asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'DockerBuildArgs': {}}, {}, x86_64, []), Function: Function(function_id='TestLambdaFunction', name='TestLambdaFunctionC089708A', functionname='TestLambdaFunction', runtime=None, memory=None, timeout=None, handler=None, imageuri='testlambdafunctionc089708a', packagetype='Image', imageconfig=None, codeuri='C:\Users\Timo\Documents\git\testcdk\cdk.out', environment=None, rolearn='arn:aws:lambda:us-east-1:XXXX:function:TestLambdaFunctionServiceRole0C9E0634', layers=[], events=None, metadata={'aws:cdk:path': 'TestcdkStack/TestLambdaFunction/Resource', 'aws:asset:path': 'asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'aws:asset:dockerfile-path': 'myimage/Dockerfile', 'aws:asset:property': 'Code.ImageUri', 'Dockerfile': 'myimage\Dockerfile', 'DockerContext': 'C:\Users\Timo\Documents\git\testcdk\cdk.out\asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'DockerBuildArgs': {}, 'SamNormalized': True, 'SamResourceId': 'TestLambdaFunction'}, inlinecode=None, codesign_config_arn=None, architectures=None, function_url_config=None, stack_path='', runtime_management_config=None)) 2023-06-12 20:42:46,171 | Building codeuri: C:\Users\Timo\Documents\git\testcdk\cdk.out runtime: None metadata: {'aws:cdk:path': 'TestcdkStack/TestLambdaFunction/Resource', 'aws:asset:path': 'asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'aws:asset:dockerfile-path': 'myimage/Dockerfile', 'aws:asset:property': 'Code.ImageUri', 'Dockerfile': 'myimage\Dockerfile', 'DockerContext': 'C:\Users\Timo\Documents\git\testcdk\cdk.out\asset.4721ec417018e85931d81e741803ba44e753dab698cfd355501d8be3c63e3123', 'DockerBuildArgs': {}} architecture: x86_64 functions: TestLambdaFunction 2023-06-12 20:42:46,174 | Building to following folder C:\Users\Timo\Documents\git\testcdk.aws-sam\build\TestLambdaFunctionC089708A 2023-06-12 20:42:46,176 | Building image for TestLambdaFunctionC089708A function 2023-06-12 20:42:46,190 | Setting DockerBuildArgs: {} for TestLambdaFunctionC089708A function

2023-06-12 20:42:46,525 | CDK Path for resource TestLambdaFunctionServiceRole0C9E0634 is ['TestcdkStack', 'TestLambdaFunction', 'ServiceRole', 'Resource'] 2023-06-12 20:42:46,531 | CDK Path for resource TestLambdaFunctionC089708A is ['TestcdkStack', 'TestLambdaFunction', 'Resource'] 2023-06-12 20:42:46,534 | CDK Path for resource CDKMetadata is ['TestcdkStack', 'CDKMetadata', 'Default'] 2023-06-12 20:42:46,538 | 3 resources found in the stack 2023-06-12 20:42:46,540 | Found Lambda function with name='TestLambdaFunctionC089708A' and Imageuri='testlambdafunctionc089708a'

Build Succeeded

The build does not fail, but no docker image is built, as can be verified by docker images.

Expected result:

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: Windows 10 Pro
  2. SAM CLI, version 1.84.0
  3. AWS region: eu-central-1
{
  "version": "1.84.0",
  "system": {
    "python": "3.8.8",
    "os": "Windows-10-10.0.19041-SP0"
  },
  "additional_dependencies": {
    "docker_engine": "24.0.2",
    "aws_cdk": "Not available",
    "terraform": "Not available"
  },
  "available_beta_feature_env_vars": [
    "SAM_CLI_BETA_FEATURES",
    "SAM_CLI_BETA_BUILD_PERFORMANCE",
    "SAM_CLI_BETA_TERRAFORM_SUPPORT",
    "SAM_CLI_BETA_RUST_CARGO_LAMBDA"
  ]
}
lucashuy commented 1 year ago

Hi, thanks for reporting this issue! I can reproduce this problem where this sample project is able to be built on Linux, but not on WIndows. Looks like it is able to find the Docker file if it is in the same folder as the DockerContext generated key, but I don't have an explanation as to why right now.

As a temporary workaround, would it be possible to move the Dockerfile to the docker/ folder instead of being in docker/myimage/?

kurt-hectic commented 1 year ago

thanks for reviewing this. I confirm that moving the Dockerfile into the parent folder is a workaround. As mentioned above, I think that "aws:asset:dockerfile-path" = "myimage/Dockerfile" in build.toml plays a role. All other paths in this file, except those of aws:asset:dockerfile-path, are translated to host-specific path format, possibly explaining why the Dockerfile is not found.

I have tried to track this in the source code, but could not not identify the area, as I am not familiar with the code. Any hint as to which part of the code is responsible for producing aws:asset:dockerfile-path in build.toml? I am happy to suggest a fix to this.

I have not found a documentation of build.toml that could shine light on the meaning of the aws:asset:dockerfile-path element.

github-actions[bot] commented 1 year ago

Patch is released in v1.94.0. Closing