GCC 完全指南 / 18 - Docker 中的 GCC
18 - Docker 中的 GCC
学习在 Docker 容器中使用 GCC,构建交叉编译容器和多架构构建流水线。
18.1 Docker 中使用 GCC 的优势
| 优势 | 说明 |
|---|---|
| 环境一致性 | 所有开发者和 CI 使用相同的编译环境 |
| 多版本共存 | 不同项目可以使用不同 GCC 版本,互不干扰 |
| 清洁环境 | 每次构建都是干净的,避免环境残留问题 |
| 交叉编译 | 轻松配置目标架构的编译环境 |
| CI/CD 集成 | 标准化的构建镜像,易于 CI 集成 |
18.2 基本 GCC Docker 镜像
基于 Ubuntu 的镜像
# Dockerfile.gcc
FROM ubuntu:22.04
# 安装基本开发工具
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
g++ \
make \
cmake \
gdb \
libc6-dev \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /src
# 默认命令
CMD ["bash"]
# 构建镜像
docker build -t my-gcc -f Dockerfile.gcc .
# 使用
docker run --rm -v $(pwd):/src my-gcc gcc -o hello main.c
docker run --rm -v $(pwd):/src my-gcc ./hello
多版本 GCC 镜像
# Dockerfile.gcc-multi
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
software-properties-common \
&& add-apt-repository ppa:ubuntu-toolchain-r/test \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
gcc-11 g++-11 \
gcc-12 g++-12 \
gcc-13 g++-13 \
make cmake \
&& rm -rf /var/lib/apt/lists/*
# 设置默认版本
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-13 100 \
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-13 100
WORKDIR /src
CMD ["bash"]
18.3 交叉编译容器
ARM64 交叉编译镜像
# Dockerfile.cross-aarch64
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc-aarch64-linux-gnu \
g++-aarch64-linux-gnu \
libc6-dev-arm64-cross \
cmake \
make \
file \
qemu-user-static \
&& rm -rf /var/lib/apt/lists/*
# 设置环境变量
ENV CROSS_TRIPLE=aarch64-linux-gnu
ENV CC=${CROSS_TRIPLE}-gcc
ENV CXX=${CROSS_TRIPLE}-g++
WORKDIR /src
CMD ["bash"]
# 构建
docker build -t cross-aarch64 -f Dockerfile.cross-aarch64 .
# 交叉编译
docker run --rm -v $(pwd):/src cross-aarch64 \
aarch64-linux-gnu-gcc -o hello_arm64 main.c
# 检查
docker run --rm -v $(pwd):/src cross-aarch64 \
file hello_arm64
多架构交叉编译镜像
# Dockerfile.cross-multi
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf \
gcc-riscv64-linux-gnu g++-riscv64-linux-gnu \
gcc-mips-linux-gnu g++-mips-linux-gnu \
libc6-dev-arm64-cross libc6-dev-armhf-cross \
cmake make file \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
# 构建脚本
COPY build-all.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/build-all.sh
CMD ["build-all.sh"]
#!/bin/bash
# build-all.sh - 为所有目标架构编译
set -e
TARGETS="aarch64-linux-gnu arm-linux-gnueabihf riscv64-linux-gnu"
for target in $TARGETS; do
echo "=== Building for $target ==="
$target-gcc -O2 -Wall -o hello_${target} main.c
file hello_${target}
done
18.4 CI/CD 集成
GitHub Actions
# .github/workflows/build.yml
name: Build with GCC
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
gcc-version: [11, 12, 13]
steps:
- uses: actions/checkout@v4
- name: Install GCC
run: |
sudo apt-get update
sudo apt-get install -y gcc-${{ matrix.gcc-version }} g++-${{ matrix.gcc-version }}
- name: Build
run: |
CC=gcc-${{ matrix.gcc-version }} CXX=g++-${{ matrix.gcc-version }} \
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
- name: Test
run: cd build && ctest --output-on-failure
cross-compile:
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
strategy:
matrix:
arch: [aarch64, armhf, riscv64]
steps:
- uses: actions/checkout@v4
- name: Install cross-compiler
run: |
apt-get update
apt-get install -y gcc-${{ matrix.arch }}-linux-gnu cmake make
- name: Build
run: |
cmake -B build \
-DCMAKE_TOOLCHAIN_FILE=cmake/${{ matrix.arch }}-toolchain.cmake
cmake --build build
GitLab CI
# .gitlab-ci.yml
stages:
- build
- test
build-gcc:
stage: build
image: gcc:13
script:
- cmake -B build -DCMAKE_BUILD_TYPE=Release
- cmake --build build
artifacts:
paths:
- build/
test:
stage: test
image: ubuntu:22.04
script:
- cd build && ctest --output-on-failure
18.5 构建优化的 Docker 镜像
多阶段构建
# Dockerfile.multistage
# 阶段 1: 编译
FROM ubuntu:22.04 AS builder
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc g++ make cmake libc6-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY . .
RUN cmake -B build -DCMAKE_BUILD_TYPE=Release \
&& cmake --build build
# 阶段 2: 运行(最小镜像)
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
libc6 \
&& rm -rf /var/lib/apt/lists/*
COPY --from=builder /src/build/hello /usr/local/bin/
CMD ["hello"]
静态链接最小镜像
# Dockerfile.static
FROM alpine:3.19 AS builder
RUN apk add --no-cache gcc musl-dev make cmake
WORKDIR /src
COPY . .
RUN cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_EXE_LINKER_FLAGS="-static" \
&& cmake --build build
# 使用 scratch(空镜像)
FROM scratch
COPY --from=builder /src/build/hello /hello
CMD ["/hello"]
18.6 Docker 中的性能分析
# Dockerfile.profiling
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc g++ make cmake \
linux-tools-generic \
valgrind \
&& rm -rf /var/lib/apt/lists/*
# perf 需要特定内核版本,可能在容器中受限
# 推荐使用 --privileged 运行
WORKDIR /src
# 使用 perf 进行性能分析(需要 --privileged)
docker run --rm --privileged -v $(pwd):/src my-profiling \
bash -c "cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo \
&& cmake --build build && cd build && perf record -g ./hello && perf report"
# 使用 Valgrind
docker run --rm -v $(pwd):/src my-profiling \
valgrind --leak-check=full ./build/hello
18.7 多架构 Docker 镜像构建
# 注册 QEMU binfmt
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# 为多个架构构建
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 \
-t myapp:latest --push .
Dockerfile 多架构支持
# Dockerfile.multiarch
FROM --platform=$BUILDPLATFORM ubuntu:22.04 AS builder
ARG TARGETPLATFORM
ARG TARGETARCH
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc make cmake \
&& if [ "$TARGETARCH" = "arm64" ]; then \
apt-get install -y gcc-aarch64-linux-gnu; \
elif [ "$TARGETARCH" = "arm" ]; then \
apt-get install -y gcc-arm-linux-gnueabihf; \
fi \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY . .
RUN if [ "$TARGETARCH" = "arm64" ]; then \
CC=aarch64-linux-gnu-gcc cmake -B build; \
elif [ "$TARGETARCH" = "arm" ]; then \
CC=arm-linux-gnueabihf-gcc cmake -B build; \
else \
cmake -B build; \
fi \
&& cmake --build build
# 最终运行镜像
FROM ubuntu:22.04
COPY --from=builder /src/build/hello /usr/local/bin/
CMD ["hello"]
要点回顾
| 要点 | 核心内容 |
|---|---|
| 基本镜像 | Ubuntu + gcc/g++,适合开发和测试 |
| 交叉编译 | gcc-aarch64-linux-gnu + QEMU 用户模式 |
| 多阶段构建 | 编译阶段 + 运行阶段,最小化最终镜像 |
| CI 集成 | GitHub Actions / GitLab CI 中使用容器构建 |
| 多架构 | docker buildx build --platform 构建多架构镜像 |
注意事项
缓存层优化: Dockerfile 中将安装依赖的
RUN指令放在COPY源码之前,利用 Docker 层缓存加速重复构建。
不要在容器中存储构建产物: 使用
-v挂载或docker cp将构建产物移到宿主机。
perf 在容器中受限: 容器中使用 perf 需要
--privileged或配置security_opt。
静态链接简化部署: 对于 C 程序,使用
-static链接可以用scratch镜像,极大减小镜像大小。
扩展阅读
- Docker 官方文档 — Docker 完整文档
- docker buildx — 多架构构建
- GCC Docker 官方镜像 — Docker Hub 上的 GCC 镜像
- Multi-stage Builds — 多阶段构建
下一步
→ 19 - 故障排查:掌握 GCC 编译和链接过程中常见错误的诊断与解决。