You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单体仓库环境下Docker本地运行带热重载的AWS Lambda问题排查

单体仓库中Docker化SAM CLI运行Lambda的问题与解决方案

场景背景

搭建了单体仓库(monorepo),包含apps目录下的frontend(基于NextJS,已通过Docker内执行next dev+挂载源码实现热重载)和pixel-api(Lambda函数)两个应用,目标是在不安装SAM CLI到宿主机的前提下,通过Docker运行SAM CLI实现Lambda本地运行+热重载。

现有配置

docker-compose.dev.yaml

version: '3.8'

services:
    pixel-api:
        build:
            context: .
            dockerfile: ./docker/Dockerfile.pixel-api-dev
        command: sam local start-api -t "${PWD}/apps/pixel-api/template.yaml" -v "${PWD}/.aws-sam/build" --host=0.0.0.0 --container-host=host.docker.internal --container-host-interface=127.0.0.1
        ports:
            - '3000:3000'
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock:ro
            - ${PWD}:${PWD}:ro
            - /dashboard/apps/pixel-api/node_modules
            - /dashboard/node_modules
        environment:
            SAM_CLI_TELEMETRY: 0
            SAM_CLI_CONTAINER_CONNECTION_TIMEOUT: 30
            sam_local_environment: 'true'

    frontend:
        container_name: frontend
        build:
            context: .
            dockerfile: ./docker/Dockerfile.frontend-dev
        env_file:
            - ./apps/frontend/envs/.env.development
        ports:
            - 8080:8080
        restart: always
        networks:
            - dashboard_network
        volumes:
            - type: bind
              source: ./apps/frontend/src
              target: /dashboard/apps/frontend/src
            - /dashboard/apps/frontend/node_modules

networks:
    dashboard_network:
        driver: bridge

frontend服务运行正常,符合预期

apps/pixel-api/template.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: SAM template for running locally API Gateway & Lambda function for Pixel API function

Globals:
    Api:
        Cors:
            AllowMethods: "'POST,OPTIONS'"
            AllowHeaders: "'content-type','x-api-key','x-amz-security-token','authorization','x-amz-user-agent','x-amz-date'"
            AllowOrigin: "'*'"
            AllowCredentials: "'*'"

Resources:
    AwsApiGateway:
        Type: AWS::Serverless::HttpApi
        Properties:
            Name: AWS API Gateway - Pixel API
            StageName: development

    MyLambdaFunction:
        Type: 'AWS::Serverless::Function'
        Properties:
            Runtime: nodejs20.x
            Handler: index.handler
            CodeUri: build
            Timeout: 30
            Description: 'Pixel API Lambda function'
            Environment:
                Variables:
                    sam_local_environment: 'true'
            Events:
                Api:
                    Type: HttpApi
                    Properties:
                        ApiId: !Ref AwsApiGateway
                        Path: /
                        Method: POST

已创建Root/apps/pixel-api/build/index.js作为Lambda入口文件

docker/Dockerfile.pixel-api-dev

FROM public.ecr.aws/docker/library/docker

ENV PIP_BREAK_SYSTEM_PACKAGES 1

RUN apk update && \
    apk add gcc py-pip python3-dev libffi-dev musl-dev && \
    pip install --upgrade pip setuptools wheel && \
    pip install --upgrade aws-sam-cli

WORKDIR /var/opt

ENTRYPOINT []
CMD ["/bin/bash"]

报错信息

执行docker-compose up -d后服务启动成功,但调用curl -X POST http://localhost:3000返回500,日志关键内容:

Mounting /MY_MACHINE_PATH/dashboard/.aws-sam/build/build as /var/task:ro,delegated, inside runtime container
START RequestId: 3e76c0ee-26bb-4250-983c-f60252289641 Version: $LATEST
2024-03-20T07:25:35.076Z        undefined       ERROR   Uncaught Exception  {"errorType":"Runtime.ImportModuleError","errorMessage":"Error: Cannot find module 'index'\nRequire stack:\n- /var/runtime/index.mjs",...}

问题解答

1. 如何在Docker容器内执行sam build?

修改pixel-api服务的command,串联执行构建与启动命令:

command: >
  sh -c "sam build -t ${PWD}/apps/pixel-api/template.yaml -b ${PWD}/.aws-sam/build &&
         sam local start-api -t ${PWD}/apps/pixel-api/template.yaml -v ${PWD}/.aws-sam/build --host=0.0.0.0 --container-host=host.docker.internal --container-host-interface=127.0.0.1"

同时需要将宿主机目录挂载权限从ro改为rw,确保容器能写入构建产物:

volumes:
  - ${PWD}:${PWD}:rw

2. 如何提前预拉取Lambda运行时镜像?

在Dockerfile.pixel-api-dev末尾添加拉取命令,构建镜像时就会预下载运行时镜像:

RUN docker pull public.ecr.aws/sam/emulation-nodejs20.x

3. 为什么Lambda找不到index模块?

核心原因是挂载路径与构建产物结构不匹配:

  • 未执行sam build时,.aws-sam/build目录为空或结构错误
  • sam build会将apps/pixel-api/build下的内容打包到.aws-sam/build/MyLambdaFunction,而非.aws-sam/build/build
  • 当前sam local start-api的-v参数挂载了错误路径,导致Lambda运行容器的/var/task目录下没有index.js

修正方案:

  1. 先执行sam build(参考问题1的方法)
  2. 调整挂载参数为构建后的函数目录:-v "${PWD}/.aws-sam/build/MyLambdaFunction:/var/task",或直接省略-v参数,SAM会自动挂载正确的构建产物目录

4. 如何实现Lambda热重载?

要实现修改Root/apps/pixel-api/build/index.js后自动刷新,需完成以下配置:

  1. 挂载源码目录:在pixel-api服务的volumes中添加:
    - ${PWD}/apps/pixel-api/build:${PWD}/apps/pixel-api/build:rw
    
  2. 自动触发构建:在容器中安装nodemon,监听源码变化自动执行sam build,修改command为:
    command: >
      sh -c "apk add nodejs npm && npm install -g nodemon &&
             nodemon --watch ${PWD}/apps/pixel-api/build -e js --exec 'sam build --no-cached -t ${PWD}/apps/pixel-api/template.yaml -b ${PWD}/.aws-sam/build' &
             sam local start-api -t ${PWD}/apps/pixel-api/template.yaml --host=0.0.0.0 --container-host=host.docker.internal --container-host-interface=127.0.0.1"
    
  3. SAM本地服务默认支持自动重载,构建产物更新后,下次调用Lambda会自动加载新代码,无需重启SAM服务

内容的提问来源于stack exchange,提问作者Tal Rofe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 13:45:56