09_apollo_docker_build子模块软件架构分析文档
1. 概述
Apollo Docker构建子模块是Apollo自动驾驶平台的核心基础设施,提供完整的Docker镜像构建与环境部署解决方案。该模块采用模块化架构,支持多架构(x86_64/aarch64)、多CUDA版本和多Ubuntu发行版配置,为开发者提供统一、可靠的开发与运行环境,确保平台在不同硬件软件环境下的一致性与可移植性。
2. 软件架构图
3. 调用流程图
4. UML类图
4.1 核心构建类图
4.2 安装器类图
5. 状态机
6. 源码分析
6.1 构建脚本核心源码分析
6.1.1 build_docker.sh主函数分析
bash
function main() {
parse_arguments "$@"
determine_target_arch_and_stage
determine_cuda_versions
determine_images_in_out
docker_build_preview
docker_build_run
}
# 调用主函数
main "$@"
build_docker.sh是整个构建系统的入口点,采用模块化设计,将构建过程分解为多个独立的功能函数:
parse_arguments:解析命令行参数,支持多种构建选项determine_target_arch_and_stage:检测目标架构和构建阶段determine_cuda_versions:确定CUDA和TensorRT版本determine_images_in_out:确定输入输出镜像名称docker_build_preview:预览构建命令docker_build_run:执行Docker构建
6.1.2 参数解析函数分析
bash
function parse_arguments() {
while [[ $# -gt 0 ]]; do
case "$1" in
-f|--dockerfile)
dockerfile="$2"
shift 2
;;
-m|--mode)
install_mode="$2"
shift 2
;;
-g|--geo)
geoloc="$2"
shift 2
;;
-d|--dist)
dist="$2"
shift 2
;;
-c|--clean)
clean_build="true"
shift
;;
*)
error "未知参数: $1"
usage
exit 1
;;
esac
done
# 参数验证
if [[ -z "${dockerfile}" ]]; then
error "必须指定Dockerfile路径"
usage
exit 1
fi
}
参数解析函数支持多种构建选项,包括:
-f|--dockerfile:指定Dockerfile路径-m|--mode:安装模式(build/download)-g|--geo:地理区域(cn/us)-d|--dist:发布版本(stable/testing)-c|--clean:干净构建
该函数还包含参数验证逻辑,确保必要参数存在。
6.1.3 Docker构建执行函数分析
bash
function docker_build_run() {
local extra_args=""
local context="$(dirname "${dockerfile}")"
local dockerfile_name="$(basename "${dockerfile}")"
# 添加构建参数
local build_args=""
build_args+=" --build-arg BASE_IMAGE=${in_image}"
build_args+=" --build-arg GEOLOC=${geoloc}"
build_args+=" --build-arg CLEAN_DEPS=${clean_deps}"
build_args+=" --build-arg INSTALL_MODE=${install_mode}"
# 执行Docker构建
docker build ${extra_args} \
--file "${dockerfile_name}" \
${build_args} \
-t "${out_image}" \
"${context}"
# 构建结果检查
if [[ $? -ne 0 ]]; then
error "Docker构建失败"
exit 1
fi
}
Docker构建执行函数负责生成并执行Docker构建命令,包括:
- 构建上下文设置
- 构建参数添加
- Docker命令执行
- 构建结果检查
6.2 安装器源码分析
6.2.1 安装器基础类分析
bash
function download_if_not_cached() {
local filename="$1"
local expected_cs="$2"
local url="$3"
local download_dir="/var/cache/apollo/distfiles"
mkdir -p "${download_dir}"
# 检查文件是否已缓存
if [[ -f "${download_dir}/${filename}" ]]; then
if verify_checksum "${download_dir}/${filename}" "${expected_cs}"; then
info "使用缓存的文件: ${filename}"
return 0
fi
fi
# 下载文件
info "下载文件: ${filename}"
wget -q -O "${download_dir}/${filename}" "${url}"
# 验证校验和
if ! verify_checksum "${download_dir}/${filename}" "${expected_cs}"; then
error "文件校验和验证失败: ${filename}"
return 1
fi
return 0
}
安装器基础类提供了通用的下载和安装功能:
download_if_not_cached:检查文件是否已缓存,若未缓存则下载verify_checksum:验证文件校验和aptGetUpdateAndInstall:更新软件源并安装包cleanup:清理临时文件
6.2.2 CyberRT依赖安装器分析
bash
function install_cyber_deps() {
apt-get -y update && \
apt-get -y install \
ncurses-dev \
libuuid1 \
uuid-dev
info "安装Protobuf ..."
bash ${CURR_DIR}/install_protobuf.sh
info "安装Fast-RTPS ..."
bash ${CURR_DIR}/install_fast-rtps.sh
# absl
bash ${CURR_DIR}/install_abseil.sh
# gflags and glog
bash ${CURR_DIR}/install_gflags_glog.sh
# Clean up cache to reduce layer size.
apt-get clean && \
rm -rf /var/lib/apt/lists/*
}
CyberRT依赖安装器负责安装CyberRT中间件所需的依赖:
- Protobuf:序列化框架
- Fast-RTPS:实时通信中间件
- Abseil:C++标准库扩展
- gflags/glog:命令行参数和日志库
6.2.3 OpenCV安装器分析
bash
function install_opencv() {
apt_get_update_and_install \
libjpeg-dev \
libpng-dev \
libtiff-dev \
libgtk2.0-dev \
libv4l-dev \
libeigen3-dev \
libopenblas-dev \
libatlas-base-dev \
libxvidcore-dev \
libx264-dev \
libopenni-dev \
libwebp-dev
pip3_install numpy
VERSION="4.4.0"
PKG_OCV="opencv-${VERSION}.tar.gz"
CHECKSUM="bb95acd849e458be7f7024d17968568d1ccd2f0681d47fd60d34ffb4b8c52563"
DOWNLOAD_LINK="https://github.com/opencv/opencv/archive/${VERSION}.tar.gz"
download_if_not_cached "${PKG_OCV}" "${CHECKSUM}" "${DOWNLOAD_LINK}"
# 构建和安装OpenCV
tar xzf ${PKG_OCV}
pushd "opencv-${VERSION}"
mkdir -p build
cd build
cmake .. \
-DCMAKE_INSTALL_PREFIX="${SYSROOT_DIR}" \
-DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DENABLE_PRECOMPILED_HEADERS=OFF \
-DOPENCV_GENERATE_PKGCONFIG=ON \
-DBUILD_EXAMPLES=OFF \
-DBUILD_DOCS=OFF \
-DBUILD_TESTS=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_PROTOBUF=OFF \
-DPROTOBUF_UPDATE_FILES=ON \
-DINSTALL_C_EXAMPLES=OFF \
-DWITH_QT=OFF \
-DWITH_GTK=ON \
-DWITH_GTK_2_X=ON \
-DWITH_IPP=OFF \
-DWITH_ITT=OFF \
-DWITH_TBB=OFF \
-DWITH_EIGEN=ON \
-DWITH_FFMPEG=ON \
-DWITH_LIBV4L=ON \
-DWITH_OPENMP=ON \
-DWITH_OPENNI=ON \
-DWITH_OPENCL=ON \
-DWITH_WEBP=ON \
-DOpenGL_GL_PREFERENCE=GLVND \
-DBUILD_opencv_python2=OFF \
-DBUILD_opencv_python3=ON \
-DBUILD_NEW_PYTHON_SUPPORT=ON \
-DPYTHON_DEFAULT_EXECUTABLE="$(which python3)" \
-DOPENCV_PYTHON3_INSTALL_PATH="/usr/local/lib/python$(py3_version)/dist-packages" \
-DOPENCV_ENABLE_NONFREE=ON \
-DCV_TRACE=OFF \
${GPU_OPTIONS} \
${EXTRA_OPTIONS}
make -j$(nproc)
make install
popd
ldconfig
ok "成功安装OpenCV ${VERSION}."
# 清理
rm -rf opencv*
}
OpenCV安装器负责安装计算机视觉库,包括:
- 系统依赖安装
- Python依赖安装
- OpenCV源码下载
- 配置、编译和安装
- 环境配置
6.3 配置管理源码分析
配置管理是Apollo Docker构建系统的重要组成部分,负责管理构建过程中的各种配置信息,包括环境变量、软件源、构建参数等。配置管理模块确保构建过程中使用正确的配置,支持不同地理区域、不同架构和不同CUDA版本的灵活配置。
6.3.1 环境变量设置分析
bash
function setup_environment() {
if [ ! -f /apollo/LICENSE ]; then
APOLLO_IN_DOCKER=false
APOLLO_PATH="/opt/apollo/neo"
APOLLO_ROOT_DIR=${APOLLO_PATH}/packages
if [ -f /.dockerenv ]; then
APOLLO_IN_DOCKER=true
fi
export APOLLO_PATH
export APOLLO_ROOT_DIR=${APOLLO_PATH}/packages
export CYBER_PATH=${APOLLO_ROOT_DIR}/cyber
export APOLLO_IN_DOCKER
export APOLLO_SYSROOT_DIR=/opt/apollo/sysroot
export CYBER_DOMAIN_ID=80
export CYBER_IP=127.0.0.1
export GLOG_log_dir=${APOLLO_PATH}/data/log
export GLOG_alsologtostderr=0
export GLOG_colorlogtostderr=1
export GLOG_minloglevel=0
export sysmo_start=0
export USE_ESD_CAN=false
fi
}
6.3.2 软件源配置分析
bash
function configure_software_sources() {
local geoloc="$1"
local arch="$(uname -m)"
if [[ "${geoloc}" == "cn" ]]; then
if [[ "${arch}" == "x86_64" ]]; then
cp /opt/apollo/rcfiles/sources.list.cn.x86_64 /etc/apt/sources.list
elif [[ "${arch}" == "aarch64" ]]; then
cp /opt/apollo/rcfiles/sources.list.cn.aarch64 /etc/apt/sources.list
fi
else
# 使用默认软件源
return 0
fi
# 更新软件源
apt-get update
}
6.4 Dockerfile源码分析
Dockerfile是Apollo Docker构建系统的核心文件之一,定义了Docker镜像的构建过程和内容。不同类型的Dockerfile对应不同的Apollo环境,如开发环境、运行时环境、CyberRT中间件环境等。
6.4.1 dev.x86_64.nvidia.dockerfile分析
dockerfile
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
ARG APOLLO_DIST
ARG GEOLOC
ARG CLEAN_DEPS
ARG INSTALL_MODE
LABEL version="1.2"
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH /opt/apollo/sysroot/bin:$PATH
ENV APOLLO_DIST ${APOLLO_DIST}
COPY installers /opt/apollo/installers
COPY rcfiles /opt/apollo/rcfiles
RUN bash /opt/apollo/installers/install_minimal_environment.sh ${GEOLOC}
RUN bash /opt/apollo/installers/install_cmake.sh
RUN bash /opt/apollo/installers/install_cyber_deps.sh ${INSTALL_MODE}
RUN bash /opt/apollo/installers/install_llvm_clang.sh
RUN bash /opt/apollo/installers/install_qa_tools.sh
RUN bash /opt/apollo/installers/install_visualizer_deps.sh
RUN bash /opt/apollo/installers/install_bazel.sh
RUN bash /opt/apollo/installers/post_install.sh cyber
WORKDIR /apollo
开发环境Dockerfile定义了Apollo平台完整的开发环境构建过程,包括以下关键部分:
6.4.2 cyber.x86_64.nvidia.dockerfile分析
dockerfile
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
ARG APOLLO_DIST
ARG GEOLOC
ARG CLEAN_DEPS
ARG INSTALL_MODE
LABEL version="1.2"
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH /opt/apollo/sysroot/bin:$PATH
ENV APOLLO_DIST ${APOLLO_DIST}
COPY installers /opt/apollo/installers
COPY rcfiles /opt/apollo/rcfiles
RUN bash /opt/apollo/installers/install_minimal_environment.sh ${GEOLOC}
RUN bash /opt/apollo/installers/install_cmake.sh
RUN bash /opt/apollo/installers/install_cyber_deps.sh ${INSTALL_MODE}
RUN bash /opt/apollo/installers/install_llvm_clang.sh
RUN bash /opt/apollo/installers/install_qa_tools.sh
RUN bash /opt/apollo/installers/install_visualizer_deps.sh
RUN bash /opt/apollo/installers/install_bazel.sh
RUN bash /opt/apollo/installers/post_install.sh cyber
WORKDIR /apollo
CyberRT镜像Dockerfile定义了CyberRT中间件环境的构建过程,与开发环境镜像类似,但包含的组件较少,主要专注于CyberRT中间件的运行环境。
7. 设计模式
Apollo Docker构建系统采用了多种设计模式,这些设计模式提高了系统的灵活性、可扩展性和可维护性。本节将详细分析系统中使用的主要设计模式。
7.1 工厂模式
工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,创建对象时不会对客户端暴露创建逻辑,而是通过一个共同的接口来指向新创建的对象。
Apollo Docker构建系统使用工厂模式创建不同类型的安装器:
bash
function create_installer() {
local installer_type="$1"
case "${installer_type}" in
"minimal")
return "MinimalEnvironmentInstaller"
;;
"cyber_deps")
return "CyberDepsInstaller"
;;
"modules_base")
return "ModulesBaseInstaller"
;;
"ordinary_modules")
return "OrdinaryModulesInstaller"
;;
"drivers_deps")
return "DriversDepsInstaller"
;;
"dreamview_deps")
return "DreamviewDepsInstaller"
;;
"gpu_support")
return "GPUSupportInstaller"
;;
"visualizer_deps")
return "VisualizerDepsInstaller"
;;
*)
error "未知的安装器类型: ${installer_type}"
return 1
;;
esac
}
7.2 策略模式
策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法独立于使用它的客户端而变化。
构建系统使用策略模式处理不同架构和CUDA版本的构建策略:
bash
function get_build_strategy() {
local arch="$1"
local cuda_version="$2"
if [[ "${arch}" == "x86_64" && "${cuda_version}" == "11.1" ]]; then
return "X86_64_CUDA_11_1_Strategy"
elif [[ "${arch}" == "x86_64" && "${cuda_version}" == "11.2" ]]; then
return "X86_64_CUDA_11_2_Strategy"
elif [[ "${arch}" == "aarch64" && "${cuda_version}" == "11.1" ]]; then
return "AARCH64_CUDA_11_1_Strategy"
elif [[ "${arch}" == "aarch64" && "${cuda_version}" == "11.2" ]]; then
return "AARCH64_CUDA_11_2_Strategy"
else
return "Default_Strategy"
fi
}
7.3 模板方法模式
模板方法模式是一种行为型设计模式,它定义了一个算法的骨架,并允许子类在不改变算法结构的情况下重定义算法的某些步骤。模板方法模式使得子类可以在不改变算法结构的情况下,重新定义算法的某些特定步骤。
安装器系统使用模板方法模式定义安装流程的骨架:
bash
function install_template() {
local installer_type="$1"
# 模板方法定义安装流程骨架
pre_install
install_dependencies
configure_environment
post_install
cleanup
}
function pre_install() {
# 钩子方法,可被子类重写
info "开始安装 ${installer_type}"
}
function install_dependencies() {
# 抽象方法,必须被子类实现
error "install_dependencies 必须被子类实现"
return 1
}
function configure_environment() {
# 钩子方法,可被子类重写
info "配置环境"
}
function post_install() {
# 钩子方法,可被子类重写
info "安装完成 ${installer_type}"
}
function cleanup() {
# 钩子方法,可被子类重写
info "清理安装文件"
}
7.4 单例模式
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。单例模式在需要控制对象创建、限制实例数量、节省资源等场景中非常有用。
构建系统使用单例模式管理配置信息:
bash
function get_config_manager() {
if [[ -z "${CONFIG_MANAGER_INSTANCE}" ]]; then
CONFIG_MANAGER_INSTANCE="$(create_config_manager)"
fi
return "${CONFIG_MANAGER_INSTANCE}"
}
7.5 观察者模式
观察者模式是一种行为型设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新。
构建系统使用观察者模式处理构建事件:
bash
function register_observer() {
local event="$1"
local observer="$2"
if [[ -z "${OBSERVERS[${event}]}" ]]; then
OBSERVERS[${event}]=""
fi
OBSERVERS[${event}]+=" ${observer}"
}
function notify_observers() {
local event="$1"
local data="$2"
if [[ -n "${OBSERVERS[${event}]}" ]]; then
for observer in ${OBSERVERS[${event}]}; do
${observer} "${data}"
done
fi
}
7.5.1 观察者模式的应用场景
在Apollo Docker构建系统中,观察者模式主要用于以下场景:
- 构建事件处理:当构建过程中的某个事件发生时,通知相关的观察者进行处理。
- 状态变化通知:当构建状态发生变化时,通知相关的组件进行更新。
- 日志记录:当发生重要事件时,通知日志记录器进行记录。
7.5.2 观察者模式的优势
- 解耦对象:观察者和被观察者之间通过接口进行通信,实现了解耦。
- 动态关系:可以动态地添加或移除观察者,实现了对象之间的动态关系。
- 广播通信:当被观察者状态发生变化时,可以同时通知所有观察者,实现了广播通信。
bash
function get_build_strategy() {
local arch="$1"
local cuda_version="$2"
if [[ "${arch}" == "x86_64" && "${cuda_version}" == "11.1" ]]; then
return "X86_64_CUDA_11_1_Strategy"
elif [[ "${arch}" == "x86_64" && "${cuda_version}" == "11.2" ]]; then
return "X86_64_CUDA_11_2_Strategy"
elif [[ "${arch}" == "aarch64" && "${cuda_version}" == "11.1" ]]; then
return "AARCH64_CUDA_11_1_Strategy"
elif [[ "${arch}" == "aarch64" && "${cuda_version}" == "11.2" ]]; then
return "AARCH64_CUDA_11_2_Strategy"
else
return "Default_Strategy"
fi
}
策略模式的应用使得不同的构建策略可以独立实现和切换,提高了系统的可维护性。
7.3 模板方法模式
安装器系统使用模板方法模式定义安装流程的骨架:
bash
function install_template() {
local installer_type="$1"
# 模板方法定义安装流程骨架
pre_install
install_dependencies
configure_environment
post_install
cleanup
}
function pre_install() {
# 钩子方法,可被子类重写
info "开始安装 ${installer_type}"
}
function install_dependencies() {
# 抽象方法,必须被子类实现
error "install_dependencies 必须被子类实现"
return 1
}
function configure_environment() {
# 钩子方法,可被子类重写
info "配置环境"
}
function post_install() {
# 钩子方法,可被子类重写
info "安装完成 ${installer_type}"
}
function cleanup() {
# 钩子方法,可被子类重写
info "清理安装文件"
}
模板方法模式的应用使得安装流程标准化,同时允许子类定制特定步骤。
7.4 单例模式
构建系统使用单例模式管理配置信息:
bash
function get_config_manager() {
if [[ -z "${CONFIG_MANAGER_INSTANCE}" ]]; then
CONFIG_MANAGER_INSTANCE="$(create_config_manager)"
fi
return "${CONFIG_MANAGER_INSTANCE}"
}
单例模式的应用确保配置信息在整个构建过程中保持一致,避免了配置不一致的问题。
7.5 观察者模式
构建系统使用观察者模式处理构建事件:
bash
function register_observer() {
local event="$1"
local observer="$2"
if [[ -z "${OBSERVERS[${event}]}" ]]; then
OBSERVERS[${event}]=""
fi
OBSERVERS[${event}]+=" ${observer}"
}
function notify_observers() {
local event="$1"
local data="$2"
if [[ -n "${OBSERVERS[${event}]}" ]]; then
for observer in ${OBSERVERS[${event}]}; do
${observer} "${data}"
done
fi
}
观察者模式的应用使得构建事件可以被多个组件监听和处理,提高了系统的扩展性。
8. 总结
Apollo Docker构建子模块是一个设计精良的容器化构建系统,采用模块化架构,支持多架构、多CUDA版本和多Ubuntu发行版的灵活配置。该系统通过分层设计、设计模式应用和完善的错误处理机制,为Apollo开发者提供了统一、可靠的开发和运行环境。随着Apollo平台的不断发展,Docker构建系统将继续演进,提供更高效、更灵活的构建解决方案,支持Apollo在不同硬件和软件环境下的广泛应用。