From 300bb163176596f665479efdaf9297db18e2166f Mon Sep 17 00:00:00 2001 From: Oscar Esteban Date: Mon, 25 Oct 2021 14:26:45 +0200 Subject: [PATCH] MAINT: Use the base ``nipreps/miniconda`` image This should ease the issues we are having with some dependencies (esp. hdf5) as well as make the building process more standardized across nipreps. In the long run it should also help minimize build time, as we converge towards multi-stage builds where source images have been minimized. --- .circleci/config.yml | 6 +- Dockerfile | 273 +++++++++++++++++++++++++++++-------------- 2 files changed, 188 insertions(+), 91 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index b8a71941..71bc8dc9 100755 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,14 +74,14 @@ jobs: set -e if [[ "$success" = "0" ]]; then echo "Pulling from local registry" - docker tag localhost:5000/ubuntu ubuntu:xenial-20201030 + docker tag localhost:5000/ubuntu ubuntu:focal-20210416 docker pull localhost:5000/dmriprep docker tag localhost:5000/dmriprep nipreps/dmriprep:latest docker tag localhost:5000/dmriprep nipreps/dmriprep else echo "Pulling from Docker Hub" - docker pull ubuntu:xenial-20201030 - docker tag ubuntu:xenial-20201030 localhost:5000/ubuntu + docker pull ubuntu:focal-20210416 + docker tag ubuntu:focal-20210416 localhost:5000/ubuntu docker push localhost:5000/ubuntu docker pull nipreps/dmriprep:latest fi diff --git a/Dockerfile b/Dockerfile index 54fc7a75..76c65e14 100755 --- a/Dockerfile +++ b/Dockerfile @@ -22,27 +22,33 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -# Use Ubuntu 16.04 LTS -FROM ubuntu:xenial-20201030 +# Use Ubuntu 20.04 LTS +FROM ubuntu:focal-20210416 # Prepare environment RUN apt-get update && \ apt-get install -y --no-install-recommends \ + apt-utils \ autoconf \ build-essential \ bzip2 \ ca-certificates \ curl \ - cython3 \ git \ libtool \ lsb-release \ pkg-config \ + unzip \ xvfb && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +ENV DEBIAN_FRONTEND="noninteractive" \ + LANG="en_US.UTF-8" \ + LC_ALL="en_US.UTF-8" + # Installing freesurfer -RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz | tar zxv --no-same-owner -C /opt \ +RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/freesurfer-Linux-centos6_x86_64-stable-pub-v6.0.1.tar.gz \ + | tar zxv --no-same-owner -C /opt \ --exclude='freesurfer/diffusion' \ --exclude='freesurfer/docs' \ --exclude='freesurfer/fsfast' \ @@ -62,7 +68,8 @@ RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/frees --exclude='freesurfer/subjects/V1_average' \ --exclude='freesurfer/trctrain' -ENV FSL_DIR="/usr/share/fsl/5.0" \ +# Simulate SetUpFreeSurfer.sh +ENV FSL_DIR="/opt/fsl-5.0.11" \ OS="Linux" \ FS_OVERRIDE=0 \ FIX_VERTEX_AREA="" \ @@ -79,107 +86,194 @@ ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \ MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \ PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH" -# Pre-cache neurodebian key -COPY .docker/neurodebian.gpg /usr/local/etc/neurodebian.gpg -# Installing Neurodebian packages (FSL, AFNI, git) -RUN curl -sSL "http://neuro.debian.net/lists/$( lsb_release -c | cut -f2 ).us-ca.full" >> /etc/apt/sources.list.d/neurodebian.sources.list && \ - apt-key add /usr/local/etc/neurodebian.gpg && \ - (apt-key adv --refresh-keys --keyserver hkp://ha.pool.sks-keyservers.net 0xA5D32F012649A5A9 || true) - -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - fsl-core=5.0.9-5~nd16.04+1 \ - fsl-mni152-templates=5.0.7-2 \ - afni=16.2.07~dfsg.1-5~nd16.04+1 \ - convert3d && \ - apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* - -ENV FSLDIR="/usr/share/fsl/5.0" \ +# FSL 5.0.11 (neurodocker build) +RUN apt-get update -qq \ + && apt-get install -y -q --no-install-recommends \ + bc \ + dc \ + file \ + libfontconfig1 \ + libfreetype6 \ + libgl1-mesa-dev \ + libgl1-mesa-dri \ + libglu1-mesa-dev \ + libgomp1 \ + libice6 \ + libxcursor1 \ + libxft2 \ + libxinerama1 \ + libxrandr2 \ + libxrender1 \ + libxt6 \ + sudo \ + wget \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && echo "Downloading FSL ..." \ + && mkdir -p /opt/fsl-5.0.11 \ + && curl -fsSL --retry 5 https://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-5.0.11-centos6_64.tar.gz \ + | tar -xz -C /opt/fsl-5.0.11 --strip-components 1 \ + --exclude "fsl/config" \ + --exclude "fsl/data/atlases" \ + --exclude "fsl/data/first" \ + --exclude "fsl/data/mist" \ + --exclude "fsl/data/possum" \ + --exclude "fsl/data/standard/bianca" \ + --exclude "fsl/data/standard/tissuepriors" \ + --exclude "fsl/doc" \ + --exclude "fsl/etc/default_flobs.flobs" \ + --exclude "fsl/etc/fslconf" \ + --exclude "fsl/etc/js" \ + --exclude "fsl/etc/luts" \ + --exclude "fsl/etc/matlab" \ + --exclude "fsl/extras" \ + --exclude "fsl/include" \ + --exclude "fsl/python" \ + --exclude "fsl/refdoc" \ + --exclude "fsl/src" \ + --exclude "fsl/tcl" \ + --exclude "fsl/bin/FSLeyes" \ + && find /opt/fsl-5.0.11/bin -type f -not \( \ + -name "applywarp" -or \ + -name "bet" -or \ + -name "bet2" -or \ + -name "convert_xfm" -or \ + -name "fast" -or \ + -name "flirt" -or \ + -name "fsl_regfilt" -or \ + -name "fslhd" -or \ + -name "fslinfo" -or \ + -name "fslmaths" -or \ + -name "fslmerge" -or \ + -name "fslroi" -or \ + -name "fslsplit" -or \ + -name "fslstats" -or \ + -name "imtest" -or \ + -name "mcflirt" -or \ + -name "melodic" -or \ + -name "prelude" -or \ + -name "remove_ext" -or \ + -name "susan" -or \ + -name "topup" -or \ + -name "zeropad" \) -delete \ + && find /opt/fsl-5.0.11/data/standard -type f -not -name "MNI152_T1_2mm_brain.nii.gz" -delete +ENV FSLDIR="/opt/fsl-5.0.11" \ + PATH="/opt/fsl-5.0.11/bin:$PATH" \ FSLOUTPUTTYPE="NIFTI_GZ" \ FSLMULTIFILEQUIT="TRUE" \ - POSSUMDIR="/usr/share/fsl/5.0" \ - LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH" \ - FSLTCLSH="/usr/bin/tclsh" \ - FSLWISH="/usr/bin/wish" \ - AFNI_MODELPATH="/usr/lib/afni/models" \ - AFNI_IMSAVE_WARNINGS="NO" \ - AFNI_TTATLAS_DATASET="/usr/share/afni/atlases" \ - AFNI_PLUGINPATH="/usr/lib/afni/plugins" -ENV PATH="/usr/lib/fsl/5.0:/usr/lib/afni/bin:$PATH" + FSLLOCKDIR="" \ + FSLMACHINELIST="" \ + FSLREMOTECALL="" \ + FSLGECUDAQ="cuda.q" \ + LD_LIBRARY_PATH="/opt/fsl-5.0.11/lib:$LD_LIBRARY_PATH" -COPY .docker/fsl-6.0/bin/topup /usr/share/fsl/5.0/bin/topup -COPY .docker/fsl-6.0/bin/imglob /usr/share/fsl/5.0/bin/imglob -COPY .docker/fsl-6.0/bin/eddy_openmp /usr/lib/fsl/5.0/eddy_openmp -COPY .docker/fsl-6.0/lib/* /usr/lib/fsl/5.0/ +# Override some FSL tools with the version 6.0 binaries +COPY .docker/fsl-6.0/bin/topup /opt/fsl-5.0.11/bin/topup +COPY .docker/fsl-6.0/bin/imglob /opt/fsl-5.0.11/bin/imglob +COPY .docker/fsl-6.0/bin/eddy_openmp /opt/fsl-5.0.11/eddy_openmp +COPY .docker/fsl-6.0/lib/* /opt/fsl-5.0.11/lib/ + +# Convert3D (neurodocker build) +RUN echo "Downloading Convert3D ..." \ + && mkdir -p /opt/convert3d-1.0.0 \ + && curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/1.0.0/c3d-1.0.0-Linux-x86_64.tar.gz/download \ + | tar -xz -C /opt/convert3d-1.0.0 --strip-components 1 \ + --exclude "c3d-1.0.0-Linux-x86_64/lib" \ + --exclude "c3d-1.0.0-Linux-x86_64/share" \ + --exclude "c3d-1.0.0-Linux-x86_64/bin/c3d_gui" +ENV C3DPATH="/opt/convert3d-1.0.0" \ + PATH="/opt/convert3d-1.0.0/bin:$PATH" + +# AFNI latest (neurodocker build) +RUN apt-get update -qq \ + && apt-get install -y -q --no-install-recommends \ + apt-utils \ + ed \ + gsl-bin \ + libglib2.0-0 \ + libglu1-mesa-dev \ + libglw1-mesa \ + libgomp1 \ + libjpeg62 \ + libxm4 \ + netpbm \ + tcsh \ + xfonts-base \ + xvfb \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.2_amd64.deb \ + && dpkg -i /tmp/multiarch.deb \ + && rm /tmp/multiarch.deb \ + && curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \ + && dpkg -i /tmp/libxp6.deb \ + && rm /tmp/libxp6.deb \ + && curl -sSL --retry 5 -o /tmp/libpng.deb http://snapshot.debian.org/archive/debian-security/20160113T213056Z/pool/updates/main/libp/libpng/libpng12-0_1.2.49-1%2Bdeb7u2_amd64.deb \ + && dpkg -i /tmp/libpng.deb \ + && rm /tmp/libpng.deb \ + && apt-get install -f \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \ + && if [ -n "$gsl2_path" ]; then \ + ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \ + fi \ + && ldconfig \ + && echo "Downloading AFNI ..." \ + && mkdir -p /opt/afni-latest \ + && curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \ + | tar -xz -C /opt/afni-latest --strip-components 1 \ + --exclude "linux_openmp_64/*.gz" \ + --exclude "linux_openmp_64/funstuff" \ + --exclude "linux_openmp_64/shiny" \ + --exclude "linux_openmp_64/afnipy" \ + --exclude "linux_openmp_64/lib/RetroTS" \ + --exclude "linux_openmp_64/meica.libs" \ + # Keep only what we use + && find /opt/afni-latest -type f -not \( \ + -name "3dTshift" -or \ + -name "3dUnifize" -or \ + -name "3dAutomask" -or \ + -name "3dvolreg" \) -delete + +ENV PATH="/opt/afni-latest:$PATH" \ + AFNI_IMSAVE_WARNINGS="NO" \ + AFNI_PLUGINPATH="/opt/afni-latest" # Installing ANTs 2.3.3 (NeuroDocker build) # Note: the URL says 2.3.4 but it is actually 2.3.3 -ENV ANTSPATH=/usr/lib/ants -RUN mkdir -p $ANTSPATH && \ - curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \ +ENV ANTSPATH="/opt/ants" \ + PATH="/opt/ants:$PATH" +WORKDIR $ANTSPATH +RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \ | tar -xzC $ANTSPATH --strip-components 1 -ENV PATH=$ANTSPATH:$PATH -# Create a shared $HOME directory -RUN useradd -m -s /bin/bash -G users dmriprep -WORKDIR /home/dmriprep -ENV HOME="/home/dmriprep" +COPY --from=nipreps/miniconda@sha256:4d0dc0fabb794e9fe22ee468ae5f86c2c8c2b4cd9d7b7fdf0c134d9e13838729 /opt/conda /opt/conda -# Installing and setting up miniconda -RUN curl -sSLO https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh && \ - bash Miniconda3-4.5.11-Linux-x86_64.sh -b -p /usr/local/miniconda && \ - rm Miniconda3-4.5.11-Linux-x86_64.sh +RUN ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \ + echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \ + echo "conda activate base" >> ~/.bashrc # Set CPATH for packages relying on compiled libs (e.g. indexed_gzip) -ENV PATH="/usr/local/miniconda/bin:$PATH" \ - CPATH="/usr/local/miniconda/include/:$CPATH" \ +ENV PATH="/opt/conda/bin:$PATH" \ + CPATH="/opt/conda/include:$CPATH" \ + LD_LIBRARY_PATH="/opt/conda/lib:$LD_LIBRARY_PATH" \ LANG="C.UTF-8" \ LC_ALL="C.UTF-8" \ PYTHONNOUSERSITE=1 -# Installing precomputed python packages -RUN conda install -y -c anaconda -c conda-forge \ - python=3.7.1 \ - graphviz=2.40 \ - git-annex \ - libxml2=2.9.8 \ - libxslt=1.1.32 \ - matplotlib=2.2 \ - mkl \ - mkl-service \ - nodejs \ - numpy=1.20 \ - pandoc=2.11 \ - pip=20.3 \ - scikit-learn=0.19 \ - scipy=1.5 \ - setuptools=51.1 \ - traits=4.6.0 \ - zlib; sync && \ - chmod -R a+rX /usr/local/miniconda; sync && \ - chmod +x /usr/local/miniconda/bin/*; sync && \ - conda build purge-all; sync && \ - conda clean -tipsy && sync - # Unless otherwise specified each process should only use one thread - nipype # will handle parallelization ENV MKL_NUM_THREADS=1 \ OMP_NUM_THREADS=1 -# Precaching fonts, set 'Agg' as default backend for matplotlib -RUN python -c "from matplotlib import font_manager" && \ - sed -i 's/\(backend *: \).*$/\1Agg/g' $( python -c "import matplotlib; print(matplotlib.matplotlib_fname())" ) - -# Installing SVGO -RUN npm install -g svgo - -# Installing bids-validator -RUN npm install -g bids-validator@1.4.0 - -# Refresh linked libraries -RUN ldconfig +# Create a shared $HOME directory +RUN useradd -m -s /bin/bash -G users dmriprep +WORKDIR /home/dmriprep +ENV HOME="/home/dmriprep" -WORKDIR /src +RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \ + echo "conda activate base" >> $HOME/.bashrc # Installing dMRIPrep COPY . /src/dmriprep @@ -187,11 +281,14 @@ ARG VERSION # Force static versioning within container RUN echo "${VERSION}" > /src/dmriprep/dmriprep/VERSION && \ echo "include dmriprep/VERSION" >> /src/dmriprep/MANIFEST.in && \ - cd /src/dmriprep && \ - pip install --no-cache-dir .[all] + /opt/conda/bin/python -m pip install --no-cache-dir "/src/dmriprep[all]" RUN find $HOME -type d -exec chmod go=u {} + && \ - find $HOME -type f -exec chmod go=u {} + + find $HOME -type f -exec chmod go=u {} + && \ + rm -rf $HOME/.npm $HOME/.conda $HOME/.empty + +# Refresh linked libraries +RUN ldconfig WORKDIR /tmp/ ENTRYPOINT ["/usr/local/miniconda/bin/dmriprep"]