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"]