I would like to create a docker container which by default uses a specific compiler version:
ARG UBUNTU_VERSION=20.04
FROM ubuntu:${UBUNTU_VERSION}
ARG COMPILER_VERSION=10
ARG PETSC_VERSION=v3.18.6
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y software-properties-common
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
RUN apt-get update
RUN apt-get install -y gcc-${COMPILER_VERSION} g++-${COMPILER_VERSION} gfortran-${COMPILER_VERSION}
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
RUN apt-get install -y build-essential git python3 openssh-server openssh-client python3-pip ffmpeg libsm6 libxext6 cmake pkg-config \
openmpi-bin libopenmpi-dev
RUN python3 -m pip install pytest numpy h5py pathlib requests pandas matplotlib plotly scikit-learn PyYAML Pillow vtk types-PyYAML pytest-cov
RUN echo "Using PETSC_VERSION: ${PETSC_VERSION}"
RUN 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
ENV PETSC_DIR /petsc
ENV PETSC_ARCH linux-gnu
ENV OMPI_ALLOW_RUN_AS_ROOT 1
ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM 1
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
This works fine and when we run the container interactively, it will select the correct compiler version by default. However, we have to use the same update-alternatives
for this purpose, once to ensure that our other packages are installed with the correct compiler, and once again in the end to ensure that anything that is executed in the container uses the specified versions as well. If we omit the last part, the originally present compiler will be used. Why is this happening, and is there a more efficient way we can design our Dockerfile?
🚨 For working Dockerfile
see end of answer. Here's some of the reasoning for how I got there.
I think you'll find that you are not actually using GCC 10 to compile the PETSc code.
Try inserting RUN gcc --version
immediately before you clone and build the PETSc repository. I think you'll find that you see something like this:
Step 13/13 : RUN gcc --version
---> Running in dc6e2b3c0095
gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
This means that, despite you setting an alternative version of the compiler prior to that it's still reverting to the default compiler. Why?
The reason for this is that something in the subsequent apt-get install
is reverting the compiler change. If you change the order of operations to this then you'll find that GCC 10 is in effect when you come to compile PETSc.
RUN apt-get install -y build-essential git python3 openssh-server openssh-client python3-pip ffmpeg libsm6 libxext6 cmake pkg-config \
openmpi-bin libopenmpi-dev
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
Now you should see this before the clone/compile step:
Step 13/13 : RUN gcc --version
---> Running in 77abf17d52bc
gcc (Ubuntu 10.5.0-1ubuntu1~20.04) 10.5.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
But now there's a snag: there's an error in the PETSc build. It prefers the default compiler version!
My suggestion is to simply remove the first set of update-alternatives
commands because they are not having any effect on the subsequent build.
Anyway, here's a complete Dockerfile
that should do what you want without duplication. I had to install an updated CMake
.
ARG UBUNTU_VERSION=20.04
FROM ubuntu:${UBUNTU_VERSION}
ARG COMPILER_VERSION=10
ARG PETSC_VERSION=v3.18.6
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y \
software-properties-common \
gnupg \
wget \
lsb-release
RUN add-apt-repository ppa:ubuntu-toolchain-r/test
# For recent CMake version.
#
RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc | gpg --dearmor - | tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
RUN echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu $(lsb_release -cs) main" | tee /etc/apt/sources.list.d/kitware.list
RUN apt-get update
RUN apt-get install -y \
gcc-${COMPILER_VERSION} \
g++-${COMPILER_VERSION} \
gfortran-${COMPILER_VERSION} \
build-essential \
git \
python3 \
openssh-server \
openssh-client \
python3-pip \
ffmpeg \
libsm6 \
libxext6 \
cmake \
pkg-config \
openmpi-bin \
libopenmpi-dev
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
RUN python3 -m pip install pytest numpy h5py pathlib requests pandas matplotlib plotly scikit-learn PyYAML Pillow vtk types-PyYAML pytest-cov
RUN echo "Using PETSC_VERSION: ${PETSC_VERSION}"
RUN 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
ENV PETSC_DIR /petsc
ENV PETSC_ARCH linux-gnu
ENV OMPI_ALLOW_RUN_AS_ROOT 1
ENV OMPI_ALLOW_RUN_AS_ROOT_CONFIRM 1