Docker容器指定编译器版本:重复update-alternatives原因及优化咨询
问题解答:Docker容器中编译器版本重置的原因及优化方案
一、两次执行update-alternatives的原因
你在安装build-essential包时,这个包依赖Ubuntu系统原生的编译器(20.04版本默认是gcc 9),安装过程中会自动调用update-alternatives,把系统原生编译器的优先级调高,直接覆盖了你第一次设置的优先级(60)。
第一次执行update-alternatives是为了让后续编译PETSc等依赖时使用指定版本的编译器,但中间安装的依赖包重置了alternatives配置,导致容器启动后默认编译器又变回系统原生版本。因此必须在所有安装操作完成后,再执行一次update-alternatives来锁定默认编译器版本。
二、更高效的Dockerfile设计方案
通过合并命令、调整执行顺序、优化缓存等方式,可以避免重复执行update-alternatives,同时减小镜像体积、提升构建效率:
ARG UBUNTU_VERSION=20.04 FROM ubuntu:${UBUNTU_VERSION} ARG COMPILER_VERSION=10 ARG PETSC_VERSION=v3.18.6 # 将构建参数转为环境变量,方便后续统一调用 ENV COMPILER_VERSION=${COMPILER_VERSION} ENV DEBIAN_FRONTEND=noninteractive # 合并所有apt操作,减少镜像层数,清理缓存减小体积 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-${COMPILER_VERSION} g++-${COMPILER_VERSION} gfortran-${COMPILER_VERSION} && \ # 安装其他依赖包 apt-get install -y --no-install-recommends build-essential git python3 openssh-server openssh-client python3-pip ffmpeg libsm6 libxext6 cmake pkg-config openmpi-bin libopenmpi-dev && \ # 清理apt缓存 apt-get clean && \ rm -rf /var/lib/apt/lists/* # 所有包安装完成后,统一设置默认编译器,用--set直接指定避免优先级被覆盖 RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${COMPILER_VERSION} 60 && \ update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${COMPILER_VERSION} 60 && \ update-alternatives --install /usr/bin/gfortran gfortran /usr/bin/gfortran-${COMPILER_VERSION} 60 && \ update-alternatives --set gcc /usr/bin/gcc-${COMPILER_VERSION} && \ update-alternatives --set g++ /usr/bin/g++-${COMPILER_VERSION} && \ update-alternatives --set gfortran /usr/bin/gfortran-${COMPILER_VERSION} # Python依赖安装添加--no-cache-dir减少镜像体积 RUN python3 -m pip install --no-cache-dir pytest numpy h5py pathlib requests pandas matplotlib plotly scikit-learn PyYAML Pillow vtk types-PyYAML pytest-cov # 编译PETSc并清理临时文件 RUN echo "Using PETSC_VERSION: ${PETSC_VERSION}" && \ git clone -b ${PETSC_VERSION} https://gitlab.com/petsc/petsc.git /petsc && \ cd /petsc && \ ./configure \ PETSC_ARCH=linux-gnu \ --with-fc=gfortran --with-cc=gcc --with-cxx=g++ \ --with-fortran-bindings \ --download-openmpi \ --with-mpi-f90module-visibility=1 \ --download-fftw \ --download-hdf5 \ --download-hdf5-fortran-bindings \ --download-fblaslapack \ --download-scalapack \ --download-ml \ --download-zlib && \ make all && \ make clean # 设置PETSc环境变量 ENV PETSC_DIR=/petsc ENV PETSC_ARCH=linux-gnu # OpenMPI相关环境变量 ENV OMPI_ALLOW_RUN_AS_ROOT=1 ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM=1
核心优化点:
- 合并所有apt相关命令,减少镜像层数,添加
--no-install-recommends避免安装冗余依赖,清理缓存大幅减小镜像体积 - 将
update-alternatives放在所有包安装完成后执行,并用--set直接指定默认编译器,彻底避免依赖包重置配置的问题,无需重复执行 - Python pip安装添加
--no-cache-dir,PETSc编译后执行make clean进一步清理临时文件
内容的提问来源于stack exchange,提问作者Yes
相关产品推荐
相关产品推荐

