|
22 | 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
23 | 23 | # SOFTWARE. |
24 | 24 |
|
25 | | -ARG BASE_IMAGE=ghcr.io/nipreps/fmriprep-base:20251006 |
| 25 | +# Ubuntu 22.04 LTS - Jammy |
| 26 | +ARG BASE_IMAGE=ubuntu:jammy-20240125 |
26 | 27 |
|
27 | 28 | # |
28 | | -# Build pixi environment |
29 | | -# The Pixi environment includes: |
30 | | -# - Python |
31 | | -# - Scientific Python stack (via conda-forge) |
32 | | -# - General Python dependencies (via PyPI) |
33 | | -# - FSL (via fslconda) |
34 | | -# - ants (via conda-forge) |
35 | | -# - connectome-workbench (via conda-forge) |
36 | | -# - ... |
| 29 | +# Build wheel |
37 | 30 | # |
38 | | -FROM ghcr.io/prefix-dev/pixi:0.53.0 AS build |
| 31 | +FROM python:slim AS src |
| 32 | +RUN pip install build |
| 33 | +RUN apt-get update && \ |
| 34 | + apt-get install -y --no-install-recommends git |
| 35 | +COPY . /src |
| 36 | +RUN python -m build /src |
| 37 | + |
| 38 | +# |
| 39 | +# Download stages |
| 40 | +# |
| 41 | + |
| 42 | +# Utilities for downloading packages |
| 43 | +FROM ${BASE_IMAGE} as downloader |
| 44 | +# Bump the date to current to refresh curl/certificates/etc |
| 45 | +RUN echo "2024.03.08" |
39 | 46 | RUN apt-get update && \ |
40 | 47 | apt-get install -y --no-install-recommends \ |
| 48 | + binutils \ |
| 49 | + bzip2 \ |
41 | 50 | ca-certificates \ |
42 | | - git && \ |
| 51 | + curl \ |
| 52 | + unzip && \ |
43 | 53 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |
44 | | -# Run post-link scripts during install, but use global to keep out of source tree |
45 | | -RUN pixi config set --global run-post-link-scripts insecure |
46 | | - |
47 | | -# Install dependencies before the package itself to leverage caching |
48 | | -RUN mkdir /app |
49 | | -COPY pixi.lock pyproject.toml /app |
50 | | -WORKDIR /app |
51 | | -RUN --mount=type=cache,target=/root/.cache/rattler pixi install -e niworkflows -e test --frozen --skip niworkflows |
52 | | -# Note that PATH gets hard-coded. Remove it and re-apply in final image |
53 | | -RUN pixi shell-hook -e niworkflows --as-is | grep -v PATH > /shell-hook.sh |
54 | | -RUN pixi shell-hook -e test --as-is | grep -v PATH > /test-shell-hook.sh |
55 | | - |
56 | | -# Finally, install the package |
57 | | -COPY . /app |
58 | | -RUN --mount=type=cache,target=/root/.cache/rattler pixi install -e niworkflows -e test --frozen |
59 | 54 |
|
60 | | -# |
61 | | -# Pre-fetch templates |
62 | | -# |
63 | | -FROM ghcr.io/astral-sh/uv:python3.12-alpine AS templates |
64 | | -ENV TEMPLATEFLOW_HOME="/templateflow" |
65 | | -RUN uv pip install --system templateflow |
66 | | -COPY docker/fetch_templates.py fetch_templates.py |
67 | | -RUN python fetch_templates.py |
| 55 | +# FreeSurfer 7.3.2 |
| 56 | +FROM downloader as freesurfer |
| 57 | +COPY docker/files/freesurfer7.3.2-exclude.txt /usr/local/etc/freesurfer7.3.2-exclude.txt |
| 58 | +RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/7.3.2/freesurfer-linux-ubuntu22_amd64-7.3.2.tar.gz \ |
| 59 | + | tar zxv --no-same-owner -C /opt --exclude-from=/usr/local/etc/freesurfer7.3.2-exclude.txt |
| 60 | + |
| 61 | +# AFNI |
| 62 | +FROM downloader as afni |
| 63 | +# Bump the date to current to update AFNI |
| 64 | +RUN echo "2024.03.08" |
| 65 | +RUN mkdir -p /opt/afni-latest \ |
| 66 | + && curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \ |
| 67 | + | tar -xz -C /opt/afni-latest --strip-components 1 \ |
| 68 | + --exclude "linux_openmp_64/*.gz" \ |
| 69 | + --exclude "linux_openmp_64/funstuff" \ |
| 70 | + --exclude "linux_openmp_64/shiny" \ |
| 71 | + --exclude "linux_openmp_64/afnipy" \ |
| 72 | + --exclude "linux_openmp_64/lib/RetroTS" \ |
| 73 | + --exclude "linux_openmp_64/lib_RetroTS" \ |
| 74 | + --exclude "linux_openmp_64/meica.libs" \ |
| 75 | + # Keep only what we use |
| 76 | + && find /opt/afni-latest -type f -not \( \ |
| 77 | + -name "3dTshift" -or \ |
| 78 | + -name "3dUnifize" -or \ |
| 79 | + -name "3dAutomask" -or \ |
| 80 | + -name "3dvolreg" \) -delete |
| 81 | + |
| 82 | +# Micromamba |
| 83 | +FROM downloader as micromamba |
| 84 | + |
| 85 | +# Install a C compiler to build extensions when needed. |
| 86 | +# traits<6.4 wheels are not available for Python 3.11+, but build easily. |
| 87 | +RUN apt-get update && \ |
| 88 | + apt-get install -y --no-install-recommends build-essential && \ |
| 89 | + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |
| 90 | + |
| 91 | +WORKDIR / |
| 92 | +# Bump the date to current to force update micromamba |
| 93 | +RUN echo "2024.03.08" |
| 94 | +RUN curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba |
68 | 95 |
|
| 96 | +ENV MAMBA_ROOT_PREFIX="/opt/conda" |
| 97 | +COPY env.yml /tmp/env.yml |
| 98 | +COPY requirements.txt /tmp/requirements.txt |
| 99 | +WORKDIR /tmp |
| 100 | +RUN micromamba create -y -f /tmp/env.yml && \ |
| 101 | + micromamba clean -y -a |
69 | 102 |
|
70 | 103 | # |
71 | 104 | # Main stage |
72 | 105 | # |
73 | | -FROM ${BASE_IMAGE} AS base |
| 106 | +FROM ${BASE_IMAGE} as main |
| 107 | + |
| 108 | +# Configure apt |
| 109 | +ENV DEBIAN_FRONTEND="noninteractive" \ |
| 110 | + LANG="en_US.UTF-8" \ |
| 111 | + LC_ALL="en_US.UTF-8" |
| 112 | + |
| 113 | +# Some baseline tools; bc is needed for FreeSurfer, so don't drop it |
| 114 | +RUN apt-get update && \ |
| 115 | + apt-get install -y --no-install-recommends \ |
| 116 | + bc \ |
| 117 | + ca-certificates \ |
| 118 | + curl \ |
| 119 | + git \ |
| 120 | + gnupg \ |
| 121 | + lsb-release \ |
| 122 | + netbase \ |
| 123 | + xvfb && \ |
| 124 | + apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* |
| 125 | + |
| 126 | +# Configure PPAs for libpng12 and libxp6 |
| 127 | +RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/linuxuprising.gpg --recv 0xEA8CACC073C3DB2A \ |
| 128 | + && GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/zeehio.gpg --recv 0xA1301338A3A48C4A \ |
| 129 | + && 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 \ |
| 130 | + && 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 |
| 131 | + |
| 132 | +# Dependencies for AFNI; requires a discontinued multiarch-support package from bionic (18.04) |
| 133 | +RUN apt-get update -qq \ |
| 134 | + && apt-get install -y -q --no-install-recommends \ |
| 135 | + ed \ |
| 136 | + gsl-bin \ |
| 137 | + libglib2.0-0 \ |
| 138 | + libglu1-mesa-dev \ |
| 139 | + libglw1-mesa \ |
| 140 | + libgomp1 \ |
| 141 | + libjpeg62 \ |
| 142 | + libpng12-0 \ |
| 143 | + libxm4 \ |
| 144 | + libxp6 \ |
| 145 | + netpbm \ |
| 146 | + tcsh \ |
| 147 | + xfonts-base \ |
| 148 | + xvfb \ |
| 149 | + && 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 \ |
| 150 | + && dpkg -i /tmp/multiarch.deb \ |
| 151 | + && rm /tmp/multiarch.deb \ |
| 152 | + && apt-get install -f \ |
| 153 | + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \ |
| 154 | + && gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \ |
| 155 | + && if [ -n "$gsl2_path" ]; then \ |
| 156 | + ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \ |
| 157 | + fi \ |
| 158 | + && ldconfig |
| 159 | + |
| 160 | +# Install files from stages |
| 161 | +COPY --from=freesurfer /opt/freesurfer /opt/freesurfer |
| 162 | +COPY --from=afni /opt/afni-latest /opt/afni-latest |
| 163 | + |
| 164 | +# Simulate SetUpFreeSurfer.sh |
| 165 | +ENV OS="Linux" \ |
| 166 | + FS_OVERRIDE=0 \ |
| 167 | + FIX_VERTEX_AREA="" \ |
| 168 | + FSF_OUTPUT_FORMAT="nii.gz" \ |
| 169 | + FREESURFER_HOME="/opt/freesurfer" |
| 170 | +ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \ |
| 171 | + FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \ |
| 172 | + MNI_DIR="$FREESURFER_HOME/mni" \ |
| 173 | + LOCAL_DIR="$FREESURFER_HOME/local" \ |
| 174 | + MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \ |
| 175 | + MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \ |
| 176 | + MNI_DATAPATH="$FREESURFER_HOME/mni/data" |
| 177 | +ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \ |
| 178 | + MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \ |
| 179 | + PATH="$FREESURFER_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH" |
| 180 | + |
| 181 | +# AFNI config |
| 182 | +ENV PATH="/opt/afni-latest:$PATH" \ |
| 183 | + AFNI_IMSAVE_WARNINGS="NO" \ |
| 184 | + AFNI_PLUGINPATH="/opt/afni-latest" |
74 | 185 |
|
75 | 186 | # Create a shared $HOME directory |
76 | 187 | RUN useradd -m -s /bin/bash -G users niworkflows |
77 | 188 | WORKDIR /home/niworkflows |
78 | | -ENV HOME="/home/niworkflows" |
79 | | - |
80 | | -COPY --link --from=templates /templateflow /home/fmriprep/.cache/templateflow |
81 | | - |
82 | | -RUN chmod -R go=u $HOME |
| 189 | +ENV HOME="/home/niworkflows" \ |
| 190 | + LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH" |
| 191 | + |
| 192 | +COPY --from=micromamba /bin/micromamba /bin/micromamba |
| 193 | +COPY --from=micromamba /opt/conda/envs/niworkflows /opt/conda/envs/niworkflows |
| 194 | + |
| 195 | +ENV MAMBA_ROOT_PREFIX="/opt/conda" |
| 196 | +RUN micromamba shell init -s bash && \ |
| 197 | + echo "micromamba activate niworkflows" >> $HOME/.bashrc |
| 198 | +ENV PATH="/opt/conda/envs/niworkflows/bin:$PATH" \ |
| 199 | + CPATH="/opt/conda/envs/niworkflows/include:$CPATH" \ |
| 200 | + LD_LIBRARY_PATH="/opt/conda/envs/niworkflows/lib:$LD_LIBRARY_PATH" |
| 201 | + |
| 202 | +COPY docker/fetch_templates.py /tmp/fetch_templates.py |
| 203 | +RUN python /tmp/fetch_templates.py && \ |
| 204 | + rm /tmp/fetch_templates.py && \ |
| 205 | + find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \ |
| 206 | + find $HOME/.cache/templateflow -type f -exec chmod go=u {} + |
| 207 | + |
| 208 | +# FSL environment |
| 209 | +ENV LANG="C.UTF-8" \ |
| 210 | + LC_ALL="C.UTF-8" \ |
| 211 | + PYTHONNOUSERSITE=1 \ |
| 212 | + FSLDIR="/opt/conda/envs/fmriprep" \ |
| 213 | + FSLOUTPUTTYPE="NIFTI_GZ" \ |
| 214 | + FSLMULTIFILEQUIT="TRUE" \ |
| 215 | + FSLLOCKDIR="" \ |
| 216 | + FSLMACHINELIST="" \ |
| 217 | + FSLREMOTECALL="" \ |
| 218 | + FSLGECUDAQ="cuda.q" |
83 | 219 |
|
84 | 220 | # Unless otherwise specified each process should only use one thread - nipype |
85 | 221 | # will handle parallelization |
86 | 222 | ENV MKL_NUM_THREADS=1 \ |
87 | 223 | OMP_NUM_THREADS=1 |
88 | 224 |
|
89 | | -COPY docker/files/nipype.cfg /home/niworkflows/.nipype/nipype.cfg |
90 | | - |
91 | | -WORKDIR /tmp |
| 225 | +# Installing niworkflows |
| 226 | +COPY --from=src /src/dist/*.whl . |
| 227 | +RUN pip install --no-cache-dir $( ls *.whl )[all] |
92 | 228 |
|
93 | | -FROM base AS test |
| 229 | +COPY docker/files/nipype.cfg /home/niworkflows/.nipype/nipype.cfg |
94 | 230 |
|
95 | | -COPY --link --from=build /app/.pixi/envs/test /app/.pixi/envs/test |
96 | | -COPY --link --from=build /test-shell-hook.sh /shell-hook.sh |
97 | | -RUN cat /shell-hook.sh >> $HOME/.bashrc |
98 | | -ENV PATH="/app/.pixi/envs/test/bin:$PATH" |
| 231 | +# Cleanup and ensure perms. |
| 232 | +RUN rm -rf $HOME/.npm $HOME/.conda $HOME/.empty && \ |
| 233 | + find $HOME -type d -exec chmod go=u {} + && \ |
| 234 | + find $HOME -type f -exec chmod go=u {} + |
99 | 235 |
|
100 | | -ENV FSLDIR="/app/.pixi/envs/test" |
| 236 | +# Final settings |
| 237 | +WORKDIR /tmp |
| 238 | +ARG BUILD_DATE |
| 239 | +ARG VCS_REF |
| 240 | +LABEL org.label-schema.build-date=$BUILD_DATE \ |
| 241 | + org.label-schema.name="niworkflows" \ |
| 242 | + org.label-schema.description="niworkflows - NeuroImaging workflows" \ |
| 243 | + org.label-schema.url="https://github.com/nipreps/niworkflows" \ |
| 244 | + org.label-schema.vcs-ref=$VCS_REF \ |
| 245 | + org.label-schema.vcs-url="https://github.com/nipreps/niworkflows" \ |
| 246 | + org.label-schema.version=$VERSION \ |
| 247 | + org.label-schema.schema-version="1.0" |
0 commit comments