交叉编译

交叉编译

什么是 Docker 中的交叉编译

交叉编译(Cross Compilation)是指在一种平台上构建出能在另一种平台上运行的二进制文件。在 Docker 上下文中,就是在 x86 机器上构建出能在 ARM 机器上运行的镜像。

传统方式 vs Buildx 方式

传统方式:为每个架构单独构建

# 在 ARM 机器上构建
docker build -t myapp:arm64 .

# 在 x86 机器上构建
docker build -t myapp:amd64 .

# 手动合并 tag
docker tag myapp:arm64 myapp:latest-arm64
docker tag myapp:amd64 myapp:latest-amd64

Buildx 方式:一次构建所有架构

docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myapp:latest --push .

编译型语言的交叉编译

Go(天然支持)

FROM --platform=$BUILDPLATFORM golang:1.21 AS builder

ARG TARGETOS
ARG TARGETARCH

WORKDIR /app
COPY . .

RUN GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /app/server

FROM scratch
COPY --from=builder /app/server /server
CMD ["/server"]

Go 编译器内置交叉编译支持,无需其他工具。

C/C++(需要交叉编译工具链)

FROM --platform=$BUILDPLATFORM ubuntu:22.04 AS builder

ARG TARGETARCH

# 安装对应架构的交叉编译工具
RUN if [ "$TARGETARCH" = "arm64" ]; then \
      apt-get update && apt-get install -y gcc-aarch64-linux-gnu; \
    elif [ "$TARGETARCH" = "amd64" ]; then \
      apt-get update && apt-get install -y gcc; \
    fi

COPY . /app
WORKDIR /app

RUN if [ "$TARGETARCH" = "arm64" ]; then \
      aarch64-linux-gnu-gcc -o /app/server main.c; \
    else \
      gcc -o /app/server main.c; \
    fi

Rust(使用对应的 target)

FROM --platform=$BUILDPLATFORM rust:1.75 AS builder

ARG TARGETARCH

RUN if [ "$TARGETARCH" = "arm64" ]; then \
      rustup target add aarch64-unknown-linux-gnu; \
    fi

COPY . /app
WORKDIR /app

RUN if [ "$TARGETARCH" = "arm64" ]; then \
      cargo build --release --target aarch64-unknown-linux-gnu; \
    else \
      cargo build --release; \
    fi

解释型语言的交叉编译

Node.js

FROM --platform=$BUILDPLATFORM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM --platform=$TARGETPLATFORM node:18-slim
COPY --from=builder /app/dist /app
CMD ["node", "/app/server.js"]

Python

FROM --platform=$BUILDPLATFORM python:3.11 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user -r requirements.txt

FROM --platform=$TARGETPLATFORM python:3.11-slim
COPY --from=builder /root/.local /root/.local
COPY . /app
CMD ["python", "/app/app.py"]

内置变量说明

Buildx 自动注入以下变量,供 Dockerfile 使用:

# 在构建阶段使用
FROM --platform=$BUILDPLATFORM golang:1.21 AS builder

ARG TARGETPLATFORM    # linux/arm64
ARG TARGETOS          # linux
ARG TARGETARCH        # arm64
ARG TARGETVARIANT     # v7(如有)
ARG BUILDPLATFORM     # linux/amd64
ARG BUILDOS           # linux
ARG BUILDARCH         # amd64

RUN echo "Building on $BUILDPLATFORM, running on $TARGETPLATFORM"

面试要点

  1. 交叉编译的核心是声明 --platform=$BUILDPLATFORM 作为构建阶段,--platform=$TARGETPLATFORM 作为运行阶段
  2. Go 是最容易实现交叉编译的语言(原生支持 GOOS/GOARCH
  3. C/C++ 需要安装对应架构的交叉编译工具链
  4. 解释型语言(Node/Python)不需要真正的交叉编译,只需在目标平台上安装运行时
  5. 内置变量 TARGETARCHTARGETOSTARGETPLATFORM 在 Buildx 中自动可用

面试官常问:交叉编译和 QEMU 模拟有什么区别?什么时候用交叉编译、什么时候用模拟?

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容