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

AWS Lambda基于Docker容器部署无法读取.env文件问题咨询

问题:Docker部署AWS Lambda后无法读取AWS密钥,且不确定最佳实践

我是AWS与Docker的新手,正在尝试从新闻API获取数据并保存至S3存储桶。本地环境中,我可通过.env文件指定的AWS密钥与访问密钥ID创建并运行Docker镜像,但将容器部署为AWS Lambda函数后,Lambda无法读取访问密钥,我不确定当前做法是否符合最佳实践。


相关代码

Dockerfile

WORKDIR ${LAMBDA_TASK_ROOT}

ADD ./semanticnewssearch/handler.py handler.py

ADD requirements.txt requirements.txt
RUN pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"

CMD ["handler.handler"]

docker-compose.yml

services:
  test:
    # 在此处可指定含变量的env文件供Docker容器使用,但仅文件名是".env"时,变量才可通过${...}在docker-compose中引用。同目录下的.env文件会自动加载到docker-compose,但需在下方environment选项映射变量或使用env_file选项,才会加载到Docker容器。
    env_file: .env
    container_name: Data_streaming
    build:
      context: .
      dockerfile: Dockerfile
    environment: # 在此处指定环境变量
      # 敏感变量存储在.env文件或系统中
      newsapikey: ${newsapikey}
      AWSAccessKeyId: ${AWSAccessKeyId}
      AWSSecretKey: ${AWSSecretKey}
      PYTHONUNBUFFERED: 1
    ports:
      - 9000:9000

handler.py脚本

import sys
import requests
from urllib import response
import json
import datetime
import time
import botocore
import boto3
from botocore.exceptions import ClientError
from dotenv import load_dotenv
load_dotenv()


NEWS_API = 'XXXXXXX'
country = 'XXXXXX'
api_key = os.getenv('newsapikey')
ACCESS_KEY = os.getenv('AWS_ACCESS_KEY_ID')
SECRET_KEY = os.getenv('AWS_SECRET_ACCESS_KEY')

url = (f'{NEWS_API}'
        f'country={country}'
        'pageSize=100&'
        f'apiKey={api_key}')

## 将新闻数据保存到S3存储桶
def save_news(data, filename):
    s3 = boto3.resource('s3',
                        aws_access_key_id=ACCESS_KEY,
                        aws_secret_access_key=SECRET_KEY)
    s3Object = s3.Object('bucketname', filename)
    try:
        s3Object.put(Body=json.dumps(data).encode('UTF-8'))
    except ClientError as e:
        print(e)
        print("出现错误,请稍后重试。")
        sys.exit()
    print("数据保存成功。")
    time.sleep(2)
    print("正在退出...")
    sys.exit()

## 从S3存储桶获取新闻数据
def get_news(filename):
    s3 = boto3.client('s3',
                        aws_access_key_id=ACCESS_KEY,
                        aws_secret_access_key=SECRET_KEY)
    try:
        data  = s3.get_object(Bucket='bukectname', Key = filename)
        data_ = data["Body"].read().decode()
        data_ = json.loads(data_)
    except ClientError as e:
        print(e)
        print("出现错误,请稍后重试。")
        sys.exit()
    print("数据获取成功。")
    return data_

def request_news():
    try:
        response = requests.get(url)
    except Exception as e:
        print(e)
        print("出现错误,请稍后重试。")
        sys.exit()
    return response.json()

def handler(event, context):
    data = request_news()
    ### 使用日期时间作为文件名保存数据
    directory = 'data/'
    filename = datetime.datetime.now().strftime('%Y-%m-%d')
    save_news(data, 'data/' + filename + '.json')
    return

问题原因与解决方案

1. Lambda无法读取密钥的直接原因

  • 环境变量名不匹配:你在docker-compose.yml中定义的是AWSAccessKeyId和AWSSecretKey,但代码中读取的是AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,部署Lambda时这些变量未正确传递。
  • .env文件未被打包:Lambda部署容器时不会包含本地的.env文件,load_dotenv()在Lambda环境中找不到文件,导致密钥读取失败。

2. 最佳实践:使用IAM角色替代硬编码密钥

AWS Lambda运行时会自动为关联的IAM角色获取临时凭证,无需手动配置密钥,这是最安全合规的做法:

  • 创建IAM角色,添加精细的S3权限(比如仅允许写入目标存储桶的s3:PutObject权限),避免使用过度宽泛的AmazonS3FullAccess。
  • 将该角色关联到你的Lambda函数。
  • 修改代码,移除手动指定密钥的逻辑,boto3会自动从Lambda环境中获取凭证:
    # 替换原有s3初始化代码
    s3 = boto3.resource('s3')
    

3. 非AWS凭证的传递方式

对于新闻API密钥这类非AWS敏感信息:

  • 在Lambda控制台的「函数配置-环境变量」中添加newsapikey变量,值设为你的API密钥。
  • 代码中保留api_key = os.getenv('newsapikey'),但移除load_dotenv()(Lambda环境会直接注入环境变量)。

4. 本地测试的兼容处理

如果需要保留本地测试能力,可在代码中添加环境判断:

import os
from dotenv import load_dotenv

# 仅本地环境加载.env文件
if os.getenv('AWS_EXECUTION_ENV') is None:
    load_dotenv()

5. Docker镜像部署Lambda的注意事项

  • 基于AWS Lambda官方Python镜像构建(比如public.ecr.aws/lambda/python:3.11),确保运行环境兼容。
  • 不要将.env文件打包进镜像,所有敏感信息通过IAM角色或Lambda环境变量处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 16:54:16