【问题标题】:Piping a stream to S3 PutObject in AWS Lambda在 AWS Lambda 中将流通过管道传输到 S3 PutObject
【发布时间】:2021-12-27 17:37:38
【问题描述】:

我正在构建一个应用程序,我需要从 lambda 动态生成 Dockerfile,然后将其压缩为 tar.gz 文件并上传到 S3,所有这些都来自 lambda 函数。但是,我从 S3 收到以下错误:

"Error: NotImplemented: A header you provided implies functionality that is not implemented"

这是我的代码:

const tar = require("tar");
const fs = require("fs");

const { S3Client, PutObjectCommand } = require("@aws-sdk/client-s3");
const { PassThrough } = require("stream");

const buildDockerFile = {
  stock: async (repository, tag, repositoryId) => {
    const input = `FROM ${repository}:${tag}`;
    const pass = new PassThrough();

    fs.writeFileSync("/tmp/Dockerfile", input);
    tar.c({ gzip: true }, ["/tmp/Dockerfile"]).pipe(pass);
    
    const params = {
      Body: pass,
      Bucket: process.env.DOCKER_IMAGES_BUCKET,
      Key: `${repositoryId}/${tag}/build-context.tar.gz`,
    };

    await s3.send(new PutObjectCommand(params));
  }
};

我正在使用第三方库 node-tar 创建 tar.gz 文件,并且我正在使用 lambda 临时存储。我将非常感谢您对此事的帮助。

【问题讨论】:

  • 您需要流式传输吗?您是否可以简单地将(微小的)Dockerfile tar/gz 到 Lambda /tmp 文件系统上,然后从那里定期将文件上传到 S3?并不是说解决流媒体问题没有价值,而是这里的主要目标。
  • 我尝试将 tar/gz 文件也保存到 /tmp 文件夹并创建读取流并传递给 S3。文件已上传,但由于某种原因已损坏。
  • 只在参数中使用Body: fs.readFileSync('/tmp/build-context.tar.gz')

标签: node.js amazon-web-services amazon-s3 aws-lambda compression


【解决方案1】:

几个小时后,我实际上找到了解决问题的方法。 AWS 提供了一个库,在这种情况下确实有帮助 - @aws-sdk/lib-storage

这是我的代码的完整工作版本:

const { S3Client } = require("@aws-sdk/client-s3");
const { Upload } = require("@aws-sdk/lib-storage");
const { PassThrough } = require("stream");
const tar = require("tar");
const fs = require("fs");

const s3 = new S3Client();

const uploadToS3 = ({ repositoryId, tag }) => {
  const pass = new PassThrough();

  const target = {
    Bucket: process.env.DOCKER_IMAGES_BUCKET,
    Key: `${repositoryId}/${tag}/context.tar.gz`,
    Body: pass,
  };

  return {
    stream: pass,
    promise: new Upload({ client: s3, params: target }),
  };
};

const buildDockerFile = {
  stock: async (repository, tag, repositoryId) => {
    const input = `FROM ${repository}:${tag}`;
    const { stream, promise } = uploadToS3({ repositoryId, tag });

    fs.writeFileSync("/tmp/Dockerfile", input);

    tar
      .c(
        {
          gzip: true,
          sync: true,
          cwd: "/tmp",
        },
        ["Dockerfile"]
      )
      .pipe(stream);

    await promise.done();
  },
};

我在此处发布此内容,以防其他人在压缩文件和 S3 方面遇到同样的问题。

【讨论】:

    猜你喜欢
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-02
    相关资源
    最近更新 更多