From adaacfbb9f6b198b9c75490036a6480e6357e5a7 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Wed, 8 May 2024 14:41:03 -0400 Subject: [PATCH] Modify Dockerfile. --- Dockerfile | 294 ++++++++++++++++++++++++++++++----------------------- env.yml | 37 +++++++ 2 files changed, 202 insertions(+), 129 deletions(-) create mode 100644 env.yml diff --git a/Dockerfile b/Dockerfile index bb1e703..1599779 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ # # MIT License # -# Copyright (c) 2023 The NiPreps Developers +# Copyright (c) The NiPreps Developers # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -22,192 +22,228 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. +# Ubuntu 22.04 LTS - Jammy +ARG BASE_IMAGE=ubuntu:jammy-20240125 + +# +# Build wheel +# FROM python:slim AS src RUN pip install build RUN apt-get update && \ apt-get install -y --no-install-recommends git -COPY . /src/fmripost_aroma -RUN python -m build /src/fmripost_aroma +COPY . /src +RUN python -m build /src -# Use Ubuntu 22.04 LTS -FROM ubuntu:jammy-20221130 +# +# Download stages +# -# Prepare environment +# Utilities for downloading packages +FROM ${BASE_IMAGE} as downloader +# Bump the date to current to refresh curl/certificates/etc +RUN echo "2023.07.20" RUN apt-get update && \ apt-get install -y --no-install-recommends \ - apt-utils \ - autoconf \ - build-essential \ + binutils \ bzip2 \ ca-certificates \ curl \ + unzip && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +# AFNI +FROM downloader as afni +# Bump the date to current to update AFNI +RUN echo "2023.07.20" +RUN 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/lib_RetroTS" \ + --exclude "linux_openmp_64/meica.libs" \ + # Keep only what we use + && find /opt/afni-latest -type f -not -name "3dTshift" -delete + +# Connectome Workbench 1.5.0 +FROM downloader as workbench +RUN mkdir /opt/workbench && \ + curl -sSLO https://www.humanconnectome.org/storage/app/media/workbench/workbench-linux64-v1.5.0.zip && \ + unzip workbench-linux64-v1.5.0.zip -d /opt && \ + rm workbench-linux64-v1.5.0.zip && \ + rm -rf /opt/workbench/libs_linux64_software_opengl /opt/workbench/plugins_linux64 && \ + strip --remove-section=.note.ABI-tag /opt/workbench/libs_linux64/libQt5Core.so.5 + +# Convert3d 1.4.0 +FROM downloader as c3d +RUN mkdir /opt/convert3d && \ + curl -fsSL --retry 5 https://sourceforge.net/projects/c3d/files/c3d/Experimental/c3d-1.4.0-Linux-gcc64.tar.gz/download \ + | tar -xz -C /opt/convert3d --strip-components 1 + +# Micromamba +FROM downloader as micromamba + +# Install a C compiler to build extensions when needed. +# traits<6.4 wheels are not available for Python 3.11+, but build easily. +RUN apt-get update && \ + apt-get install -y --no-install-recommends build-essential && \ + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +WORKDIR / +# Bump the date to current to force update micromamba +RUN echo "2024.02.06" +RUN curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba + +ENV MAMBA_ROOT_PREFIX="/opt/conda" +COPY env.yml /tmp/env.yml +WORKDIR /tmp +RUN micromamba create -y -f /tmp/env.yml && \ + micromamba clean -y -a + +# UV_USE_IO_URING for apparent race-condition (https://github.com/nodejs/node/issues/48444) +# Check if this is still necessary when updating the base image. +ENV PATH="/opt/conda/envs/fmripost_aroma/bin:$PATH" \ + UV_USE_IO_URING=0 +RUN npm install -g svgo@^3.2.0 bids-validator@^1.14.0 && \ + rm -r ~/.npm + +# +# Main stage +# +FROM ${BASE_IMAGE} as fmripost_aroma + +# Configure apt +ENV DEBIAN_FRONTEND="noninteractive" \ + LANG="en_US.UTF-8" \ + LC_ALL="en_US.UTF-8" + +# Some baseline tools; bc is needed for FreeSurfer, so don't drop it +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + bc \ + ca-certificates \ + curl \ git \ gnupg \ - libtool \ lsb-release \ netbase \ - 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" +# Configure PPAs for libpng12 and libxp6 +RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/linuxuprising.gpg --recv 0xEA8CACC073C3DB2A \ + && GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/zeehio.gpg --recv 0xA1301338A3A48C4A \ + && echo "deb [signed-by=/usr/share/keyrings/linuxuprising.gpg] https://ppa.launchpadcontent.net/linuxuprising/libpng12/ubuntu jammy main" > /etc/apt/sources.list.d/linuxuprising.list \ + && echo "deb [signed-by=/usr/share/keyrings/zeehio.gpg] https://ppa.launchpadcontent.net/zeehio/libxp/ubuntu jammy main" > /etc/apt/sources.list.d/zeehio.list -# FSL 6.0.5.1 +# Dependencies for AFNI; requires a discontinued multiarch-support package from bionic (18.04) RUN apt-get update -qq \ && apt-get install -y -q --no-install-recommends \ - bc \ - dc \ - file \ - libfontconfig1 \ - libfreetype6 \ - libgl1-mesa-dev \ - libgl1-mesa-dri \ + ed \ + gsl-bin \ + libglib2.0-0 \ libglu1-mesa-dev \ + libglw1-mesa \ 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-6.0.5.1 \ - && curl -fsSL --retry 5 https://fsl.fmrib.ox.ac.uk/fsldownloads/fsl-6.0.5.1-centos7_64.tar.gz \ - | tar -xz -C /opt/fsl-6.0.5.1 --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-6.0.5.1/bin -type f -not \( \ - -name "melodic" -or \ - -name "susan" -or \) -delete \ - && find /opt/fsl-6.0.5.1/data/standard -type f -not -name "MNI152_T1_2mm_brain.nii.gz" -delete -ENV FSLDIR="/opt/fsl-6.0.5.1" \ - PATH="/opt/fsl-6.0.5.1/bin:$PATH" \ - FSLOUTPUTTYPE="NIFTI_GZ" \ - FSLMULTIFILEQUIT="TRUE" \ - FSLLOCKDIR="" \ - FSLMACHINELIST="" \ - FSLREMOTECALL="" \ - FSLGECUDAQ="cuda.q" \ - LD_LIBRARY_PATH="/opt/fsl-6.0.5.1/lib:$LD_LIBRARY_PATH" + libjpeg62 \ + libpng12-0 \ + libxm4 \ + libxp6 \ + netpbm \ + tcsh \ + xfonts-base \ + xvfb \ + && curl -sSL --retry 5 -o /tmp/multiarch.deb http://archive.ubuntu.com/ubuntu/pool/main/g/glibc/multiarch-support_2.27-3ubuntu1.5_amd64.deb \ + && dpkg -i /tmp/multiarch.deb \ + && rm /tmp/multiarch.deb \ + && apt-get install -f \ + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ + && 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 -# Configure PPA for libpng12 -RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/linuxuprising.gpg --recv 0xEA8CACC073C3DB2A \ - && echo "deb [signed-by=/usr/share/keyrings/linuxuprising.gpg] https://ppa.launchpadcontent.net/linuxuprising/libpng12/ubuntu jammy main" > /etc/apt/sources.list.d/linuxuprising.list - -# Installing and setting up ICA_AROMA -WORKDIR /opt/ICA-AROMA -RUN curl -sSL "https://github.com/oesteban/ICA-AROMA/archive/v0.4.5.tar.gz" \ - | tar -xzC /opt/ICA-AROMA --strip-components 1 && \ - chmod +x /opt/ICA-AROMA/ICA_AROMA.py -ENV PATH="/opt/ICA-AROMA:$PATH" \ - AROMA_VERSION="0.4.5" - -WORKDIR /opt -RUN curl -sSLO https://www.humanconnectome.org/storage/app/media/workbench/workbench-linux64-v1.5.0.zip && \ - unzip workbench-linux64-v1.5.0.zip && \ - rm workbench-linux64-v1.5.0.zip && \ - rm -rf /opt/workbench/libs_linux64_software_opengl /opt/workbench/plugins_linux64 && \ - strip --remove-section=.note.ABI-tag /opt/workbench/libs_linux64/libQt5Core.so.5 - # ABI tags can interfere when running on Singularity +# Install files from stages +COPY --from=afni /opt/afni-latest /opt/afni-latest +COPY --from=workbench /opt/workbench /opt/workbench +COPY --from=c3d /opt/convert3d/bin/c3d_affine_tool /usr/bin/c3d_affine_tool + +# AFNI config +ENV PATH="/opt/afni-latest:$PATH" \ + AFNI_IMSAVE_WARNINGS="NO" \ + AFNI_PLUGINPATH="/opt/afni-latest" +# Workbench config ENV PATH="/opt/workbench/bin_linux64:$PATH" \ LD_LIBRARY_PATH="/opt/workbench/lib_linux64:$LD_LIBRARY_PATH" -# nipreps/miniconda:py39_4.12.0rc0 -COPY --from=nipreps/miniconda@sha256:5aa4d2bb46e7e56fccf6e93ab3ff765add74e79f96ffa00449504b4869790cb9 /opt/conda /opt/conda - -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="/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 - -RUN conda install -y -n base \ - -c anaconda \ - -c conda-forge \ - convert3d=1.3.0 \ - && sync \ - && conda clean -afy; sync \ - && rm -rf ~/.conda ~/.cache/pip/*; sync \ - && ldconfig - -# Unless otherwise specified each process should only use one thread - nipype -# will handle parallelization -ENV MKL_NUM_THREADS=1 \ - OMP_NUM_THREADS=1 - # Create a shared $HOME directory RUN useradd -m -s /bin/bash -G users fmripost_aroma WORKDIR /home/fmripost_aroma ENV HOME="/home/fmripost_aroma" \ LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH" -RUN echo ". /opt/conda/etc/profile.d/conda.sh" >> $HOME/.bashrc && \ - echo "conda activate base" >> $HOME/.bashrc +COPY --from=micromamba /bin/micromamba /bin/micromamba +COPY --from=micromamba /opt/conda/envs/fmripost_aroma /opt/conda/envs/fmripost_aroma -RUN /opt/conda/bin/python -m pip install --no-cache-dir --upgrade templateflow +ENV MAMBA_ROOT_PREFIX="/opt/conda" +RUN micromamba shell init -s bash && \ + echo "micromamba activate fmripost_aroma" >> $HOME/.bashrc +ENV PATH="/opt/conda/envs/fmripost_aroma/bin:$PATH" \ + CPATH="/opt/conda/envs/fmripost_aroma/include:$CPATH" \ + LD_LIBRARY_PATH="/opt/conda/envs/fmripost_aroma/lib:$LD_LIBRARY_PATH" # Precaching atlases COPY scripts/fetch_templates.py fetch_templates.py - -RUN /opt/conda/bin/python fetch_templates.py && \ +RUN python fetch_templates.py && \ rm fetch_templates.py && \ find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \ find $HOME/.cache/templateflow -type f -exec chmod go=u {} + +# FSL environment +ENV LANG="C.UTF-8" \ + LC_ALL="C.UTF-8" \ + PYTHONNOUSERSITE=1 \ + FSLDIR="/opt/conda/envs/fmripost_aroma" \ + FSLOUTPUTTYPE="NIFTI_GZ" \ + FSLMULTIFILEQUIT="TRUE" \ + FSLLOCKDIR="" \ + FSLMACHINELIST="" \ + FSLREMOTECALL="" \ + FSLGECUDAQ="cuda.q" + +# Unless otherwise specified each process should only use one thread - nipype +# will handle parallelization +ENV MKL_NUM_THREADS=1 \ + OMP_NUM_THREADS=1 + # Installing fMRIPost-AROMA -COPY --from=src /src/fmripost_aroma/dist/*.whl . -RUN /opt/conda/bin/python -m pip install --no-cache-dir $( ls *.whl )[all] +COPY --from=src /src/dist/*.whl . +RUN pip install --no-cache-dir $( ls *.whl )[test] RUN find $HOME -type d -exec chmod go=u {} + && \ find $HOME -type f -exec chmod go=u {} + && \ rm -rf $HOME/.npm $HOME/.conda $HOME/.empty +# For detecting the container ENV IS_DOCKER_8395080871=1 RUN ldconfig WORKDIR /tmp -ENTRYPOINT ["/opt/conda/bin/fmripost_aroma"] +ENTRYPOINT ["/opt/conda/envs/fmripost_aroma/bin/fmripost_aroma"] ARG BUILD_DATE ARG VCS_REF ARG VERSION LABEL org.label-schema.build-date=$BUILD_DATE \ org.label-schema.name="fMRIPost-AROMA" \ - org.label-schema.description="fMRIPost-AROMA - robust fMRI preprocessing tool" \ - org.label-schema.url="http://fmripost_aroma.org" \ + org.label-schema.description="fMRIPost-AROMA - fMRI post-processing with AROMA" \ + org.label-schema.url="https://fmripost_aroma.org" \ org.label-schema.vcs-ref=$VCS_REF \ org.label-schema.vcs-url="https://github.com/nipreps/fmripost_aroma" \ org.label-schema.version=$VERSION \ diff --git a/env.yml b/env.yml new file mode 100644 index 0000000..4001c42 --- /dev/null +++ b/env.yml @@ -0,0 +1,37 @@ +name: fmripost_aroma +channels: + - https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/ + - conda-forge +# Update this ~yearly; last updated Jan 2024 +dependencies: + - python=3.11 + # Needed for svgo and bids-validator; consider moving to deno + - nodejs=20 + # Intel Math Kernel Library for numpy + - mkl=2023.2.0 + - mkl-service=2.4.0 + # git-annex for templateflow users with DataLad superdatasets + - git-annex=*=alldep* + # Base scientific python stack; required by FSL, so pinned here + - numpy=1.26 + - scipy=1.11 + - matplotlib=3.8 + - pandas=2.2 + - h5py=3.10 + # Dependencies compiled against numpy, best to stick with conda + - nitime=0.10 + - scikit-image=0.22 + - scikit-learn=1.4 + # Utilities + - graphviz=9.0 + - pandoc=3.1 + # Workflow dependencies: ANTs + - ants=2.5 + # Workflow dependencies: FSL (versions pinned in 6.0.7.7) + - fsl-bet2=2111.4 + - fsl-melodic=2111.3 + - fsl-miscmaths=2203.2 + - fsl-susan=2111.0 + - pip +variables: + FSLOUTPUTTYPE: NIFTI_GZ