Skip to content

Commit ce98c49

Browse files
authored
Merge pull request #992 from nipreps/revert-990-pixi
Revert "chore: Use pixi to manage test environment"
2 parents ce8bb67 + 81b0d7f commit ce98c49

File tree

6 files changed

+480
-5415
lines changed

6 files changed

+480
-5415
lines changed

.dockerignore

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,3 @@ fmriprep.egg-info/**/*
1212
fmriprep.egg-info
1313
.eggs/**/*
1414
.eggs
15-
16-
.venv
17-
.pixi
18-
.tox

Dockerfile

Lines changed: 197 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -22,79 +22,226 @@
2222
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2323
# SOFTWARE.
2424

25-
ARG BASE_IMAGE=ghcr.io/nipreps/fmriprep-base:20251006
25+
# Ubuntu 22.04 LTS - Jammy
26+
ARG BASE_IMAGE=ubuntu:jammy-20240125
2627

2728
#
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
3730
#
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"
3946
RUN apt-get update && \
4047
apt-get install -y --no-install-recommends \
48+
binutils \
49+
bzip2 \
4150
ca-certificates \
42-
git && \
51+
curl \
52+
unzip && \
4353
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
5954

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
6895

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
69102

70103
#
71104
# Main stage
72105
#
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"
74185

75186
# Create a shared $HOME directory
76187
RUN useradd -m -s /bin/bash -G users niworkflows
77188
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"
83219

84220
# Unless otherwise specified each process should only use one thread - nipype
85221
# will handle parallelization
86222
ENV MKL_NUM_THREADS=1 \
87223
OMP_NUM_THREADS=1
88224

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

93-
FROM base AS test
229+
COPY docker/files/nipype.cfg /home/niworkflows/.nipype/nipype.cfg
94230

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 {} +
99235

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"

env.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: niworkflows
2+
channels:
3+
- https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/
4+
- conda-forge
5+
# Update this ~yearly; last updated Mar 2025
6+
dependencies:
7+
- python=3.12
8+
# Intel Math Kernel Library for numpy
9+
- mkl=2024.2.2
10+
- mkl-service=2.4.2
11+
# Base scientific python stack; required by FSL, so pinned here
12+
- numpy=1.26
13+
- scipy=1.15
14+
- matplotlib=3.9
15+
- pandas=2.2
16+
- h5py=3.13
17+
# Dependencies compiled against numpy, best to stick with conda
18+
- scikit-image=0.25
19+
- scikit-learn=1.6
20+
# Utilities
21+
- graphviz=11.0
22+
# Workflow dependencies: ANTs
23+
- ants=2.5
24+
# 5.4.1 and 5.4.2 cause segfaults with ants
25+
# Try to remove this ASAP
26+
# https://github.com/conda-forge/ants-feedstock/issues/19
27+
- libitk=5.4.0
28+
# Workflow dependencies: FSL (versions pinned in 6.0.7.13)
29+
- fsl-bet2=2111.8
30+
- fsl-flirt=2111.2
31+
- fsl-fast4=2111.3
32+
- fsl-mcflirt=2111.0
33+
- fsl-miscmaths=2203.2
34+
- pip
35+
- pip:
36+
- -r requirements.txt

0 commit comments

Comments
 (0)