如何在Github Actions AMD64 Runner上通过CDK构建ARM64 Docker镜像
在AMD64架构的Github Actions Runner上构建ARM64 Docker镜像失败的解决方案
问题背景
在AMD64架构的Github Actions Runner上构建用于ARM64 Graviton Fargate服务的Docker镜像时,执行RUN命令失败,报错如下:
Warning: The requested image's platform (linux/arm64/v8) does not match the detected host platform (linux/amd64) and no specific platform was requested ---> Running in 025f2d97f759 exec /bin/sh: exec format error Removing intermediate container f2c3858b0496 The command '/bin/sh -c apt-get update' returned a non-zero code: 1 ---> 02ceb19d6208 [66%] fail: docker build --tag cdkasset-7e1b96b9aea331ad2efd7e6fbf6f075033eca830469ea4ab8d57bf4a8eeb86cd --file Dockerfile --platform linux/arm64 . exited with error code 1: The command '/bin/sh -c apt-get update' returned a non-zero code: 1
相关配置文件如下:
Github Actions工作流配置
name: Deploy on: push: branches: - main permissions: id-token: write contents: read jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 cache: "npm" - run: npm ci - uses: docker/setup-buildx-action@v2 - uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::123456789098:role/cicd-role aws-region: us-west-2 - run: npx cdk deploy --all --require-approval never env: DOCKER_BUILDKIT: 1
Dockerfile
# We create our own image rather than using cloudflare/cloudfared because that is an ultra # slimmed-down image that does not have a shell. We need the shell to be present to call # the image with a command like `["sh", "-c", "cloudflared tunnel run --token $TOKEN"] wherin # we can use available environment variables which represent passed-in values from AWS Secrets # Manager. FROM --platform=linux/arm64 debian:stretch-slim RUN apt-get update RUN apt-get dist-upgrade --yes RUN apt-get install curl --yes # Install cloudflared RUN curl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb RUN dpkg -i cloudflared.deb RUN rm cloudflared.deb
CDK构造代码片段
import { aws_ecr_assets, aws_ecs, } from "aws-cdk-lib"; import { Construct } from "constructs"; export class Tunnel extends Construct { constructor(scope: Construct, id: string, props: TunnelProps) { super(scope, id); const taskDefinition = new aws_ecs.FargateTaskDefinition( this, "TunnelDefinition", { runtimePlatform: { cpuArchitecture: aws_ecs.CpuArchitecture.ARM64, }, } ); taskDefinition.addContainer("container", { image: aws_ecs.AssetImage.fromAsset("./", { platform: aws_ecr_assets.Platform.LINUX_ARM64, }), }); new aws_ecs.FargateService(this, "Tunnel", { serviceName: "cloudflare-tunnel", cluster: props.cluster, taskDefinition, }); } } export interface TunnelProps { cluster: aws_ecs.ICluster; loadBalancerDnsName: string; }
解决方案
可以在AMD64架构的Github Actions Runner上构建ARM64镜像,问题出在多平台构建的支持配置上,按以下步骤修复:
1. 启用QEMU交叉编译支持
添加QEMU安装步骤,让AMD64主机可以执行ARM64架构的二进制指令:
- uses: docker/setup-qemu-action@v2 with: platforms: arm64
2. 调整Buildx配置以支持多平台
修改docker/setup-buildx-action步骤,启用多平台构建能力:
- uses: docker/setup-buildx-action@v2 with: install: true driver-opts: | network=host
3. 强化CDK镜像构建的平台参数
在CDK的AssetImage.fromAsset配置中,额外添加构建参数明确指定目标平台:
image: aws_ecs.AssetImage.fromAsset("./", { platform: aws_ecr_assets.Platform.LINUX_ARM64, buildArgs: { "TARGETPLATFORM": "linux/arm64" } }),
4. 可选:更新Dockerfile基础镜像版本
将debian:stretch-slim替换为更新的debian:bullseye-slim,提升ARM64架构的兼容性:
FROM --platform=linux/arm64 debian:bullseye-slim
修改后的完整Github Actions工作流
name: Deploy on: push: branches: - main permissions: id-token: write contents: read jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 18 cache: "npm" - run: npm ci # 安装QEMU支持ARM64交叉编译 - uses: docker/setup-qemu-action@v2 with: platforms: arm64 # 启用Buildx多平台构建能力 - uses: docker/setup-buildx-action@v2 with: install: true driver-opts: | network=host - uses: aws-actions/configure-aws-credentials@v2 with: role-to-assume: arn:aws:iam::123456789098:role/cicd-role aws-region: us-west-2 - run: npx cdk deploy --all --require-approval never env: DOCKER_BUILDKIT: 1
原理说明
报错exec /bin/sh: exec format error是因为AMD64主机无法直接运行ARM64架构的二进制文件,QEMU提供了二进制翻译能力,让AMD64系统可以执行ARM64指令;Buildx则负责协调跨平台镜像的构建流程,两者配合即可实现AMD64主机上构建ARM64镜像的需求。
内容的提问来源于stack exchange,提问作者alukach
相关产品推荐
相关产品推荐

