在CDK的CodePipeline阶段配置Docker构建密钥的问题
解决CDK CodePipeline中DockerImageAsset访问私有Git依赖的问题
在CodePipeline构建流程中,Docker镜像构建需要通过poetry install拉取私有GitHub仓库的依赖。本地通过docker build --secret注入私钥可以正常构建,但在CDK配置时,无法让DockerImageAsset访问前置ShellStep生成的私钥文件,导致构建失败。
核心思路
DockerImageAsset默认使用源码目录作为构建上下文,无法直接访问Pipeline中ShellStep生成的临时文件。需要通过Pipeline Workspace实现步骤间的文件共享,将私钥写入共享Workspace后,让DockerImageAsset将该Workspace纳入构建上下文,再在Dockerfile中引用密钥。
具体实现步骤
1. 创建共享Pipeline Workspace
在Pipeline中定义一个共享的Workspace,用于存放私钥文件:
from aws_cdk import ( pipelines, aws_codebuild as codebuild, aws_secretsmanager as secretsmanager, aws_ecr_assets as ecr_assets, ) # 创建共享工作空间 secret_workspace = pipelines.Workspace(name="git-secret-workspace")
2. 编写ShellStep获取私钥并写入Workspace
添加前置ShellStep,从Secrets Manager拉取私钥,写入Workspace的文件中,并设置正确的文件权限(Git要求私钥权限为600):
# 从Secrets Manager获取私钥的ShellStep fetch_secret_step = pipelines.ShellStep( "FetchGitPrivateKey", commands=[ # 获取私钥并写入临时文件 'aws secretsmanager get-secret-value --secret-id "github-private-key" --query SecretString --output text > /tmp/git_private_key', # 复制到共享工作空间并设置权限 'cp /tmp/git_private_key $CODEBUILD_SRC_DIR_git-secret-workspace/id_rsa', 'chmod 600 $CODEBUILD_SRC_DIR_git-secret-workspace/id_rsa' ], # 授予CodeBuild角色读取Secrets Manager的权限 role_policy_statements=[ secretsmanager.Secret.from_secret_name_v2(self, "GitSecret", "github-private-key").grant_read() ], # 指定使用的共享工作空间 additional_workspaces=[secret_workspace] )
3. 修改Dockerfile以使用共享的私钥
更新Dockerfile,在poetry install前通过--secret引用共享Workspace中的私钥文件:
FROM python:3.11-slim WORKDIR /app # 复制依赖配置文件 COPY pyproject.toml poetry.lock ./ # 构建时注入私钥,拉取私有Git依赖 RUN --mount=type=secret,id=git_private_key,target=/root/.ssh/id_rsa \ chmod 600 /root/.ssh/id_rsa && \ ssh-keyscan github.com >> /root/.ssh/known_hosts && \ poetry install --no-root --no-dev && \ rm /root/.ssh/id_rsa # 复制应用代码 COPY . . CMD ["python", "app.py"]
4. 配置DockerImageAsset引用共享Workspace
创建DockerImageAsset时,将共享Workspace添加到构建上下文,并通过CodeBuild的Secret机制引用私钥:
# 创建Docker镜像资产 docker_asset = ecr_assets.DockerImageAsset( self, "AppImage", directory="./app", # 主源码目录 extra_hash=secret_workspace.path, # 私钥变化时触发镜像重构 # 关联共享工作空间中的私钥文件 build_secrets={ "git_private_key": codebuild.Secret.from_file_in_workspace("git-secret-workspace", "id_rsa") } )
5. 在Pipeline中编排步骤依赖
确保Docker镜像构建步骤依赖于私钥获取步骤,保证私钥文件已生成:
# 创建Pipeline pipeline = pipelines.CodePipeline( self, "MyPipeline", synth=pipelines.ShellStep("Synth", input=pipelines.CodePipelineSource.git_hub("your/repo", "main"), commands=["npm ci", "npm run synth"] ) ) # 添加镜像构建阶段 build_stage = pipelines.Stage(self, "BuildImageStage") build_stage.add_post( pipelines.CodeBuildStep( "BuildDockerImage", commands=[ f'docker build --secret id=git_private_key,src={secret_workspace.path}/id_rsa -t {docker_asset.image_uri} ./app', f'docker push {docker_asset.image_uri}' ], additional_workspaces=[secret_workspace], # 授予推送镜像到ECR的权限 role_policy_statements=[ docker_asset.repository.grant_push() ] ) ) # 设置阶段依赖,确保先获取私钥再构建镜像 pipeline.add_stage(build_stage, pre=[fetch_secret_step])
关键注意事项
- 权限配置:确保CodePipeline和CodeBuild的执行角色拥有Secrets Manager读取权限、ECR推送权限。
- 私钥权限:必须将私钥文件权限设置为600,否则Git会拒绝使用该密钥。
- Workspace关联:通过
additional_workspaces将共享Workspace传递给需要的步骤,确保文件可访问。 - 重构触发:使用
extra_hash关联Workspace内容,私钥更新时自动触发镜像重构。
内容的提问来源于stack exchange,提问作者Jaygee Lastname
相关产品推荐
相关产品推荐

