如何在AWS Lambda中添加自定义库与二进制文件?
AWS Lambda Python3.8/3.9 自定义二进制依赖添加方案
Python3.6 及更早版本的 Lambda 运行时基于 Amazon Linux 1,预装了大量系统级依赖库;升级到基于 Amazon Linux 2 的 Python3.8/3.9 运行时后,很多原有内置库被移除,需要自行打包对应二进制依赖,以下是经过生产验证的可行实现方案:
方案1:同环境编译构建部署包
这是踩坑最少、兼容性最稳的方案,核心逻辑是所有二进制依赖必须在和 Lambda 运行时完全一致的环境下编译,避免跨系统、跨发行版的动态库依赖不匹配问题:
- 拉取 AWS 官方提供的对应 Python 版本 Lambda 容器镜像,比如适配 Python3.9 就用
public.ecr.aws/lambda/python:3.9 - 启动容器进入交互终端,Python 类依赖直接执行
pip install -r requirements.txt -t ./package安装到本地打包目录;如果是系统级二进制依赖(比如 ffmpeg、ImageMagick、各类 C/C++ 编译的组件),直接通过 yum 在容器内安装对应包,再把编译生成的二进制文件、关联的.so动态依赖库全部拷贝到打包目录 - 给所有二进制文件加上可执行权限,和业务代码一起打包成 zip 压缩包直接部署即可
- 代码里调用自定义二进制时,优先用
/var/task/[你的二进制相对路径]的绝对路径调用,同时可以在函数初始化阶段把自定义库路径加到环境变量,避免找不到依赖:
import os os.environ['PATH'] = '/var/task/bin:' + os.environ.get('PATH', '') os.environ['LD_LIBRARY_PATH'] = '/var/task/lib:' + os.environ.get('LD_LIBRARY_PATH', '')
方案2:用 Lambda Layer 封装公共依赖
如果多个 Lambda 函数需要共用同一套二进制依赖,不要重复把依赖打进每个函数的部署包,单独封装成 Layer 更便于维护:
- 按照方案1的容器编译流程拿到所有需要的二进制、动态库、Python 依赖,按照 Layer 的规范目录结构存放:二进制文件放
bin目录,动态库放lib目录,Python 第三方包放python目录 - 把整个目录结构打包成 zip 上传创建 Lambda Layer,绑定到目标函数后,Layer 内的文件会被自动解压到
/opt路径下 - 函数初始化时只需要把
/opt/bin加到 PATH、/opt/lib加到 LD_LIBRARY_PATH 即可直接调用,后续依赖更新只需要升级 Layer 版本,不需要改动业务代码部署包
方案3:使用静态编译的独立二进制
如果需要的二进制工具体积不大,可以直接使用静态编译版本,这类二进制不依赖任何系统级动态库,不需要额外拷贝关联依赖,放进部署包就能直接运行:
- 常见工具比如 ffmpeg、puppeteer 依赖的 Chrome 组件等,都有已经适配 Amazon Linux 2 的公开静态编译版本,可以直接使用,省去自己编译的步骤
- 注意不要随意下载其他平台编译的静态二进制,必须确认是针对 Amazon Linux 2 环境、和你 Lambda 函数架构(x86_64/arm64)一致的编译版本,否则会出现指令集不兼容无法运行的问题
避坑提醒
- 不要直接在本地 macOS、Windows 或者普通 Ubuntu 环境编译二进制后上传到 Lambda,90%以上的运行报错都是底层环境不匹配导致的
- Lambda 部署包有大小限制:直接上传 zip 包最大 50MB,传 S3 后引用最大 250MB,包含 Layer 的总解压后大小不能超过 250MB,如果依赖体积过大建议精简无用组件,或者拆分多个 Layer
- Python3.8 及以上版本的 Amazon Linux 2 运行时,默认不会把函数部署目录加到 PATH 和 LD_LIBRARY_PATH 路径中,必须手动在代码中添加对应路径,否则会出现找不到文件、找不到动态依赖的报错
内容的提问来源于stack exchange,提问作者DilLip_Chowdary
相关产品推荐
相关产品推荐

