Skip to content

Commit ce8bb67

Browse files
authored
Merge pull request #990 from effigies/pixi
chore: Use pixi to manage test environment
2 parents 03d056c + 696beb9 commit ce8bb67

File tree

6 files changed

+5415
-480
lines changed

6 files changed

+5415
-480
lines changed

.dockerignore

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

Dockerfile

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

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

2827
#
29-
# Build wheel
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+
# - ...
3037
#
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"
38+
FROM ghcr.io/prefix-dev/pixi:0.53.0 AS build
4639
RUN apt-get update && \
4740
apt-get install -y --no-install-recommends \
48-
binutils \
49-
bzip2 \
5041
ca-certificates \
51-
curl \
52-
unzip && \
42+
git && \
5343
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
5459

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
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
9568

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
10269

10370
#
10471
# Main stage
10572
#
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"
73+
FROM ${BASE_IMAGE} AS base
18574

18675
# Create a shared $HOME directory
18776
RUN useradd -m -s /bin/bash -G users niworkflows
18877
WORKDIR /home/niworkflows
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"
78+
ENV HOME="/home/niworkflows"
79+
80+
COPY --link --from=templates /templateflow /home/fmriprep/.cache/templateflow
81+
82+
RUN chmod -R go=u $HOME
21983

22084
# Unless otherwise specified each process should only use one thread - nipype
22185
# will handle parallelization
22286
ENV MKL_NUM_THREADS=1 \
22387
OMP_NUM_THREADS=1
22488

225-
# Installing niworkflows
226-
COPY --from=src /src/dist/*.whl .
227-
RUN pip install --no-cache-dir $( ls *.whl )[all]
228-
22989
COPY docker/files/nipype.cfg /home/niworkflows/.nipype/nipype.cfg
23090

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 {} +
235-
236-
# Final settings
23791
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"
92+
93+
FROM base AS test
94+
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"
99+
100+
ENV FSLDIR="/app/.pixi/envs/test"

env.yml

Lines changed: 0 additions & 36 deletions
This file was deleted.

0 commit comments

Comments
 (0)