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

部署Lambda时将Chrome二进制文件复制到/tmp目录的方法

问题分析与解决方案

1. Serverless配置的直接错误

你当前的Serverless配置缺少Resources层级,正确的CloudFormation自定义资源配置需要嵌套在resources.Resources下,否则Serverless框架不会识别这个自定义资源。修正后的配置如下:

resources:
  Resources:
    CopyChromeBinaries:
      Type: Custom::CopyChromeBinaries
      Properties:
        ServiceToken: arn:aws:lambda:region:ACCOUNT_ID:function:CopyChromeBinaries

2. 核心思路误区:部署阶段无法写入Lambda的/tmp目录

需要明确:Lambda的/tmp目录是实例级临时存储,只有当Lambda实例启动后才会存在,部署阶段(CloudFormation运行自定义资源时)没有活跃的Lambda实例,因此辅助Lambda无法在部署阶段将Chrome二进制文件写入主Lambda的/tmp。你的这个思路从根本上不可行。

3. 可行的替代方案

方案一:Lambda初始化阶段从S3下载二进制文件

将Chrome二进制文件打包后上传到S3桶,在主Lambda的初始化代码段(而非请求处理函数内)添加从S3下载并解压到/tmp的逻辑。每个Lambda实例只会执行一次初始化操作,后续请求复用已解压的二进制文件,避免重复开销:

// 主Lambda初始化代码(在exports.handler之外)
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const fs = require('fs');
const unzip = require('unzipper');

async function initChrome() {
  const bucketName = 'your-chrome-bucket';
  const key = 'chrome-headless.zip';
  const tmpPath = '/tmp/chrome';

  // 检查/tmp是否已存在Chrome,避免重复下载
  if (!fs.existsSync(tmpPath)) {
    const response = await s3.getObject({ Bucket: bucketName, Key: key }).promise();
    await fs.createWriteStream('/tmp/chrome.zip').write(response.Body);
    await fs.createReadStream('/tmp/chrome.zip').pipe(unzip.Extract({ path: tmpPath })).promise();
    // 设置执行权限
    fs.chmodSync(`${tmpPath}/chrome`, 0o755);
  }
}

// 执行初始化
initChrome().catch(err => console.error('Chrome初始化失败:', err));

exports.handler = async (event) => {
  // 业务逻辑,此时Chrome已在/tmp目录
  const chromePath = '/tmp/chrome/chrome';
  // ... 运行无头Chrome的代码
};

同时需要给主Lambda添加S3读取权限,在Serverless配置中添加:

provider:
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:GetObject
      Resource: arn:aws:s3:::your-chrome-bucket/chrome-headless.zip

方案二:使用Lambda层(若二进制压缩后符合大小限制)

如果Chrome二进制文件的压缩包大小不超过50MB(Lambda层压缩包上限),可以将其打包为Lambda层,部署时附加到主Lambda。层会被自动解压到/opt目录,无需手动处理:

  1. 将Chrome二进制文件放入层包的bin目录(或直接根目录),打包为zip
  2. 在Serverless配置中引用该层:
functions:
  mainLambda:
    handler: handler.main
    layers:
      - arn:aws:lambda:region:ACCOUNT_ID:layer:ChromeHeadless:1

注意:Lambda层的未压缩大小不能超过250MB,且主Lambda代码包+所有层的未压缩总大小不能超过250MB,若Chrome未压缩后接近或超过这个值,此方案不适用。

4. 辅助Lambda的正确使用场景(可选)

如果你希望在部署阶段完成二进制文件的预处理(比如上传到S3),可以用自定义资源辅助Lambda来自动化这个步骤,但无法直接写入Lambda实例的/tmp。比如在部署时将本地的Chrome二进制包上传到S3,避免手动操作:

resources:
  Resources:
    UploadChromeToS3:
      Type: Custom::UploadChromeToS3
      Properties:
        ServiceToken: arn:aws:lambda:region:ACCOUNT_ID:function:UploadChromeToS3
        BucketName: your-chrome-bucket
        LocalFilePath: ./chrome-headless.zip

此时辅助Lambda需要具备S3上传权限,且能读取部署时传递的参数完成上传操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 05:32:36