1. 简介
在 DevOps 实践中,安全地将 AWS 凭证传递给 Docker 容器是一项关键任务。无论我们是将容器部署在 EC2 实例上,还是运行在本地机器上,合理管理这些凭证都可以显著提升安全性和效率。
本文将介绍几种将 AWS 凭证传递给 Docker 容器的方法。我们将从最推荐的方式 —— 使用 IAM 角色(适用于 EC2 实例)开始,然后介绍适用于其他场景的方法,包括构建时注入、环境变量、挂载凭证文件、Docker Secrets 等。
2. 使用 IAM 角色(适用于 Amazon EC2)
对于运行在 EC2 实例上的 Docker 容器,使用 IAM 角色是最安全、最便捷的凭证管理方式。它避免了将凭证硬编码进应用或镜像中,也无需手动管理密钥。
2.1 创建信任策略文件
首先,我们需要创建一个信任策略文件 trust-policy.json
,用于定义哪个服务(如 EC2)可以假设这个角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
2.2 创建 IAM 角色
使用 AWS CLI 创建 IAM 角色:
$ aws iam create-role --role-name MyDockerRole --assume-role-policy-document file://trust-policy.json
2.3 为角色附加权限策略
例如,我们可以为角色附加只读访问 S3 的策略:
$ aws iam attach-role-policy --role-name MyDockerRole --policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
验证是否附加成功:
$ aws iam list-attached-role-policies --role-name MyDockerRole
2.4 将角色附加到 EC2 实例
使用以下命令将 IAM 角色绑定到 EC2 实例:
$ aws ec2 associate-iam-instance-profile --instance-id i-1234567890abcdef0 --iam-instance-profile Name=MyDockerProfile
绑定后,运行在该 EC2 上的 Docker 容器将自动继承该角色的临时凭证,AWS SDK(如 boto3)会自动从元数据服务获取这些凭证,无需手动配置。
示例代码(Python boto3):
import boto3
s3 = boto3.client('s3')
response = s3.list_buckets()
print(response['Buckets'])
⚠️ 注意:该方法仅适用于 EC2 实例。如果你的容器运行在其他环境中(如本地或 Kubernetes),需要考虑其他方法。
3. 在 Docker 构建阶段注入密钥
在构建阶段可能需要访问 AWS 资源(如从 S3 下载依赖),此时可以通过以下方式安全注入凭证:
3.1 使用多阶段构建
多阶段构建可以确保凭证只存在于中间镜像中,不会出现在最终镜像中:
# 构建阶段
FROM node:14 AS builder
COPY . /app
WORKDIR /app
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
ENV AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
ENV AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
RUN npm install
RUN npm run build
# 最终阶段
FROM node:14
COPY --from=builder /app/dist /app/dist
CMD ["node", "app/dist/index.js"]
构建命令:
$ docker build \
--build-arg AWS_ACCESS_KEY_ID=your_access_key_id \
--build-arg AWS_SECRET_ACCESS_KEY=your_secret_access_key \
-t my_image .
3.2 使用 BuildKit 管理密钥
BuildKit 支持将密钥作为文件挂载,构建完成后自动删除:
$ export DOCKER_BUILDKIT=1
Dockerfile 示例:
# syntax=docker/dockerfile:1.3
FROM python:3.9
RUN pip install awscli
RUN --mount=type=secret,id=aws,target=/root/.aws/credentials aws s3 cp s3://my-bucket/my-file /my-file
构建命令:
$ DOCKER_BUILDKIT=1 docker build --secret id=aws,src=$HOME/.aws/credentials -t my_image .
✅ 优点:密钥不留在镜像中;适合 CI/CD 流程。
4. 通过环境变量传递凭证
这是最简单的方法,但存在安全风险,不建议在生产环境中使用。
4.1 使用 docker run
$ docker run \
-e AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE \
-e AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY \
-e AWS_DEFAULT_REGION=us-west-2 \
my-docker-image
4.2 使用 docker-compose.yml
version: '3'
services:
myapp:
image: my-docker-image
environment:
- AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
- AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- AWS_DEFAULT_REGION=us-west-2
⚠️ 风险:环境变量可能暴露在日志、shell 历史记录中。
4.3 多 Profile 支持
如果你使用了多个 AWS profile,可以设置 AWS_PROFILE
:
environment:
- AWS_PROFILE=your_profile
运行前先在本地设置:
$ export AWS_PROFILE=your_profile
$ docker-compose up
5. 挂载凭证文件为卷
将 AWS 凭证文件挂载为卷是一种安全且灵活的方式:
$ docker run -v $HOME/.aws/credentials:/root/.aws/credentials:ro my_image
Docker Compose 配置:
version: '3'
services:
app:
image: my_image
volumes:
- $HOME/.aws/credentials:/root/.aws/credentials:ro
✅ 优点:
- 凭证不在镜像中
- 可以通过修改主机文件实现密钥更新
⚠️ 注意事项:
- 挂载时务必使用
:ro
(只读) - 控制主机上凭证文件的访问权限
- 不要在不同环境(开发/生产)中复用同一份凭证
6. 使用 Docker Swarm Secrets
如果你使用 Docker Swarm,可以使用其内置的 Secrets 管理功能:
创建 Secret:
$ docker secret create aws_creds $HOME/.aws/credentials
docker-compose.yml 配置:
version: '3.7'
secrets:
aws_creds:
external: true
services:
app:
image: my_image
secrets:
- source: aws_creds
target: /root/.aws/credentials
uid: '1000'
gid: '1000'
mode: 0400
部署服务:
$ docker stack deploy -c docker-compose.yml my_stack
✅ 优点:
- Secrets 在 Swarm 内加密存储
- 只有指定服务可访问
- 支持密钥轮换
⚠️ 注意:Docker Secrets 仅适用于 Swarm 模式,不适用于所有部署场景。
7. 总结
本文介绍了多种将 AWS 凭证传递给 Docker 容器的方法,每种方法都有其适用场景:
方法 | 适用场景 | 安全性 | 管理复杂度 |
---|---|---|---|
IAM 角色(EC2) | EC2 实例上运行容器 | ✅ 高 | ⭐ 低 |
BuildKit 密钥挂载 | 构建阶段访问 AWS 资源 | ✅ 高 | ⭐ 中 |
环境变量 | 开发/测试环境 | ❌ 低 | ⭐ 低 |
挂载凭证文件 | 本地开发或测试 | ✅ 中 | ⭐ 中 |
Docker Swarm Secrets | 使用 Swarm 部署 | ✅ 高 | ⭐ 高 |
根据你的部署环境和需求选择合适的方式。避免在生产环境中使用环境变量传递凭证,优先考虑 IAM 角色或 Secret 管理工具。