Skip to content

Commit 86947cc

Browse files
REF: multi-stage docker build
1 parent 27ef533 commit 86947cc

File tree

3 files changed

+487
-98
lines changed

3 files changed

+487
-98
lines changed

Dockerfile

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

25-
# Use Ubuntu 20.04 LTS
26-
FROM nipreps/miniconda:py38_1.4.2
25+
# Ubuntu 22.04 LTS - Jammy
26+
ARG BASE_IMAGE=ubuntu:jammy-20230308
2727

28-
ENV DEBIAN_FRONTEND=noninteractive
28+
#
29+
# fMRIPrep wheel
30+
#
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/fmriprep
36+
RUN python -m build /src/fmriprep
37+
38+
#
39+
# Download stages
40+
#
41+
42+
# Utilities for downloading packages
43+
FROM ${BASE_IMAGE} as downloader
44+
RUN apt-get update && \
45+
apt-get install -y --no-install-recommends \
46+
binutils \
47+
bzip2 \
48+
ca-certificates \
49+
curl \
50+
unzip && \
51+
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
2952

3053
# Installing freesurfer
54+
FROM downloader as freesurfer
3155
COPY docker/files/freesurfer-exclude.txt /usr/local/etc/freesurfer-exclude.txt
3256
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 \
3357
| tar zxv --no-same-owner -C /opt --exclude-from=/usr/local/etc/freesurfer-exclude.txt
3458

35-
# Simulate SetUpFreeSurfer.sh
36-
ENV OS="Linux" \
37-
FS_OVERRIDE=0 \
38-
FIX_VERTEX_AREA="" \
39-
FSF_OUTPUT_FORMAT="nii.gz" \
40-
FREESURFER_HOME="/opt/freesurfer"
41-
ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \
42-
FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \
43-
MNI_DIR="$FREESURFER_HOME/mni" \
44-
LOCAL_DIR="$FREESURFER_HOME/local" \
45-
MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \
46-
MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \
47-
MNI_DATAPATH="$FREESURFER_HOME/mni/data"
48-
ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
49-
MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
50-
PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"
59+
# AFNI
60+
FROM downloader as afni
61+
# Bump the date to current to update AFNI
62+
RUN echo "2023.04.04"
63+
RUN mkdir -p /opt/afni-latest \
64+
&& curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \
65+
| tar -xz -C /opt/afni-latest --strip-components 1 \
66+
--exclude "linux_openmp_64/*.gz" \
67+
--exclude "linux_openmp_64/funstuff" \
68+
--exclude "linux_openmp_64/shiny" \
69+
--exclude "linux_openmp_64/afnipy" \
70+
--exclude "linux_openmp_64/lib/RetroTS" \
71+
--exclude "linux_openmp_64/lib_RetroTS" \
72+
--exclude "linux_openmp_64/meica.libs" \
73+
# Keep only what we use
74+
&& find /opt/afni-latest -type f -not \( \
75+
-name "3dTshift" -or \
76+
-name "3dUnifize" -or \
77+
-name "3dAutomask" -or \
78+
-name "3dvolreg" \) -delete
79+
80+
# ANTs 2.3.3
81+
FROM downloader as ants
82+
# Note: the URL says 2.3.4 but it is actually 2.3.3
83+
RUN mkdir /opt/ants && \
84+
curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
85+
| tar -xzC /opt/ants --strip-components 1
86+
87+
# Micromamba
88+
FROM downloader as micromamba
89+
WORKDIR /
90+
# Bump the date to current to force update micromamba
91+
RUN echo "2023.04.05"
92+
RUN curl -Ls https://micro.mamba.pm/api/micromamba/linux-64/latest | tar -xvj bin/micromamba
93+
94+
# Install FSL and Convert3D from conda packages
95+
# Specific FSL pins are derived from
96+
# https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/releases/fsl-6.0.6.2_linux-64.yml
97+
ENV MAMBA_ROOT_PREFIX="/opt/conda"
98+
COPY env.yml /tmp/env.yml
99+
RUN micromamba create -y -f /tmp/env.yml && \
100+
micromamba clean -y -a
101+
102+
ENV PATH="/opt/conda/envs/fprodents/bin:$PATH"
103+
RUN /opt/conda/envs/fprodents/bin/npm install -g svgo@^2.8 bids-validator@1.11.0 && \
104+
rm -r ~/.npm
51105

52-
# AFNI latest (neurodocker build)
106+
COPY requirements.txt /tmp/requirements.txt
107+
RUN /opt/conda/envs/fprodents/bin/pip install --no-cache-dir -r /tmp/requirements.txt
108+
109+
#
110+
# Main stage
111+
#
112+
FROM ${BASE_IMAGE} as fmriprep
113+
114+
# Configure apt
115+
ENV DEBIAN_FRONTEND="noninteractive" \
116+
LANG="en_US.UTF-8" \
117+
LC_ALL="en_US.UTF-8"
118+
119+
RUN apt-get update && \
120+
apt-get install -y --no-install-recommends \
121+
ca-certificates \
122+
curl \
123+
gnupg \
124+
lsb-release \
125+
netbase \
126+
xvfb && \
127+
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
128+
129+
130+
# Configure PPAs for libpng12 and libxp6
131+
RUN GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/linuxuprising.gpg --recv 0xEA8CACC073C3DB2A \
132+
&& GNUPGHOME=/tmp gpg --keyserver hkps://keyserver.ubuntu.com --no-default-keyring --keyring /usr/share/keyrings/zeehio.gpg --recv 0xA1301338A3A48C4A \
133+
&& 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 \
134+
&& 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
135+
136+
# Dependencies for AFNI; requires a discontinued multiarch-support package from bionic (18.04)
53137
RUN apt-get update -qq \
54138
&& apt-get install -y -q --no-install-recommends \
55-
apt-utils \
56139
ed \
57140
gsl-bin \
58141
libglib2.0-0 \
59142
libglu1-mesa-dev \
60143
libglw1-mesa \
61144
libgomp1 \
62145
libjpeg62 \
146+
libpng12-0 \
63147
libxm4 \
148+
libxp6 \
64149
netpbm \
65150
tcsh \
66151
xfonts-base \
67152
xvfb \
68-
&& apt-get clean \
69-
&& rm -rf /var/lib/apt/lists/* \
70153
&& 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 \
71154
&& dpkg -i /tmp/multiarch.deb \
72155
&& rm /tmp/multiarch.deb \
73-
&& curl -sSL --retry 5 -o /tmp/libxp6.deb http://mirrors.kernel.org/debian/pool/main/libx/libxp/libxp6_1.0.2-2_amd64.deb \
74-
&& dpkg -i /tmp/libxp6.deb \
75-
&& rm /tmp/libxp6.deb \
76-
&& 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 \
77-
&& dpkg -i /tmp/libpng.deb \
78-
&& rm /tmp/libpng.deb \
79156
&& apt-get install -f \
80-
&& apt-get clean \
81-
&& rm -rf /var/lib/apt/lists/* \
157+
&& apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
82158
&& gsl2_path="$(find / -name 'libgsl.so.19' || printf '')" \
83159
&& if [ -n "$gsl2_path" ]; then \
84160
ln -sfv "$gsl2_path" "$(dirname $gsl2_path)/libgsl.so.0"; \
85161
fi \
86-
&& ldconfig \
87-
&& echo "Downloading AFNI ..." \
88-
&& mkdir -p /opt/afni-latest \
89-
&& curl -fsSL --retry 5 https://afni.nimh.nih.gov/pub/dist/tgz/linux_openmp_64.tgz \
90-
| tar -xz -C /opt/afni-latest --strip-components 1 \
91-
--exclude "linux_openmp_64/*.gz" \
92-
--exclude "linux_openmp_64/funstuff" \
93-
--exclude "linux_openmp_64/shiny" \
94-
--exclude "linux_openmp_64/afnipy" \
95-
--exclude "linux_openmp_64/lib/RetroTS" \
96-
--exclude "linux_openmp_64/meica.libs" \
97-
# Keep only what we use
98-
&& find /opt/afni-latest -type f -not \( \
99-
-name "3dTshift" -or \
100-
-name "3dUnifize" -or \
101-
-name "3dAutomask" -or \
102-
-name "3dvolreg" \) -delete
162+
&& ldconfig
163+
164+
# Install files from stages
165+
COPY --from=freesurfer /opt/freesurfer /opt/freesurfer
166+
COPY --from=afni /opt/afni-latest /opt/afni-latest
167+
COPY --from=ants /opt/ants /opt/ants
168+
169+
# Simulate SetUpFreeSurfer.sh
170+
ENV OS="Linux" \
171+
FS_OVERRIDE=0 \
172+
FIX_VERTEX_AREA="" \
173+
FSF_OUTPUT_FORMAT="nii.gz" \
174+
FREESURFER_HOME="/opt/freesurfer"
175+
ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \
176+
FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \
177+
MNI_DIR="$FREESURFER_HOME/mni" \
178+
LOCAL_DIR="$FREESURFER_HOME/local" \
179+
MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \
180+
MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \
181+
MNI_DATAPATH="$FREESURFER_HOME/mni/data"
182+
ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
183+
MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
184+
PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"
103185

104186
ENV PATH="/opt/afni-latest:$PATH" \
105187
AFNI_IMSAVE_WARNINGS="NO" \
106188
AFNI_PLUGINPATH="/opt/afni-latest"
107189

108-
# Installing ANTs 2.3.3 (NeuroDocker build)
109-
# Note: the URL says 2.3.4 but it is actually 2.3.3
110190
ENV ANTSPATH="/opt/ants" \
111191
PATH="/opt/ants:$PATH"
112-
WORKDIR $ANTSPATH
113-
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
114-
| tar -xzC $ANTSPATH --strip-components 1
192+
193+
# Create a shared $HOME directory
194+
RUN useradd -m -s /bin/bash -G users fmriprep
195+
WORKDIR /home/fmriprep
196+
ENV HOME="/home/fmriprep" \
197+
LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH"
198+
199+
COPY --from=micromamba /bin/micromamba /bin/micromamba
200+
COPY --from=micromamba /opt/conda/envs/fprodents /opt/conda/envs/fprodents
201+
202+
ENV MAMBA_ROOT_PREFIX="/opt/conda"
203+
RUN micromamba shell init -s bash && \
204+
echo "micromamba activate fprodents" >> $HOME/.bashrc
205+
ENV PATH="/opt/conda/envs/fprodents/bin:$PATH" \
206+
CPATH="/opt/conda/envs/fprodents/include:$CPATH" \
207+
LD_LIBRARY_PATH="/opt/conda/envs/fprodents/lib:$LD_LIBRARY_PATH"
208+
209+
# Precaching atlases
210+
RUN python -c "import templateflow; \
211+
templateflow.update(); \
212+
templateflow.api.get('Fischer344', extension=['.nii', '.nii.gz'])" && \
213+
find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
214+
find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
215+
115216

116217
# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
117-
ENV PATH="/opt/conda/bin:$PATH" \
118-
CPATH="/opt/conda/include:$CPATH" \
119-
LD_LIBRARY_PATH="/opt/conda/lib:$LD_LIBRARY_PATH" \
120-
LANG="C.UTF-8" \
218+
ENV LANG="C.UTF-8" \
121219
LC_ALL="C.UTF-8" \
122220
PYTHONNOUSERSITE=1 \
123-
FSLDIR="/opt/conda" \
221+
FSLDIR="/opt/conda/envs/fprodents" \
124222
FSLOUTPUTTYPE="NIFTI_GZ" \
125223
FSLMULTIFILEQUIT="TRUE" \
126224
FSLLOCKDIR="" \
127225
FSLMACHINELIST="" \
128226
FSLREMOTECALL="" \
129227
FSLGECUDAQ="cuda.q"
130228

131-
# Install FSL and Convert3D from conda packages
132-
# Specific FSL pins are derived from
133-
# https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/releases/fsl-6.0.6.2_linux-64.yml
134-
RUN conda install -y -n base \
135-
-c anaconda \
136-
-c https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/ \
137-
-c conda-forge \
138-
convert3d=1.3.0 \
139-
fsl-flirt=2111.0 \
140-
fsl-fast4=2111.0 \
141-
fsl-fugue=2201.2 \
142-
fsl-mcflirt=2111.0 \
143-
fsl-melodic=2111.1 \
144-
fsl-miscmaths=2203.2 \
145-
fsl-topup=2203.1 \
146-
fsl-susan=2111.0 \
147-
&& sync \
148-
&& conda clean -afy; sync \
149-
&& rm -rf ~/.conda ~/.cache/pip/*; sync \
150-
&& ldconfig
151-
152229
# Unless otherwise specified each process should only use one thread - nipype
153230
# will handle parallelization
154231
ENV MKL_NUM_THREADS=1 \
155232
OMP_NUM_THREADS=1
156233

157-
# Create a shared $HOME directory
158-
RUN useradd -m -s /bin/bash -G users fmriprep
159-
WORKDIR /home/fmriprep
160-
ENV HOME="/home/fmriprep"
161-
162-
# Precaching atlases
163-
RUN python -c "import templateflow; \
164-
templateflow.update(); \
165-
templateflow.api.get('Fischer344', extension=['.nii', '.nii.gz'])" && \
166-
find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
167-
find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
168-
169-
COPY . /src/fmriprep
170-
ARG VERSION
171-
# Force static versioning within container
172-
RUN echo "${VERSION}" > /src/fmriprep/fprodents/VERSION && \
173-
echo "include fprodents/VERSION" >> /src/fmriprep/MANIFEST.in && \
174-
/opt/conda/bin/python -m pip install --no-cache-dir "/src/fmriprep[all]"
234+
# Installing FMRIPREP
235+
COPY --from=src /src/fmriprep/dist/*.whl .
236+
RUN pip install --no-cache-dir $( ls *.whl )[all]
175237

176238
RUN find $HOME -type d -exec chmod go=u {} + && \
177239
find $HOME -type f -exec chmod go=u {} + && \
@@ -181,7 +243,7 @@ ENV IS_DOCKER_8395080871=1
181243

182244
RUN ldconfig
183245
WORKDIR /tmp
184-
ENTRYPOINT ["/opt/conda/bin/fprodents"]
246+
ENTRYPOINT ["/opt/conda/envs/fprodents/"]
185247

186248
ARG BUILD_DATE
187249
ARG VCS_REF

env.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: fprodents
2+
channels:
3+
- https://fsl.fmrib.ox.ac.uk/fsldownloads/fslconda/public/
4+
- conda-forge
5+
# Update this ~yearly; last updated May 2023
6+
dependencies:
7+
- python >=3.10,<3.11
8+
# Needed for svgo and bids-validator; consider moving to deno
9+
- nodejs=16
10+
# Intel Math Kernel Library for numpy
11+
- mkl=2022.1
12+
- mkl-service=2.4
13+
# Base scientific python stack; required by FSL, so pinned here
14+
- numpy=1.24
15+
- scipy=1.10
16+
- matplotlib=3.7
17+
- pandas=2.0
18+
- h5py=3.8
19+
# Dependencies compiled against numpy, best to stick with conda
20+
- nitime=0.9
21+
- scikit-image=0.20
22+
- scikit-learn=1.2
23+
# Utilities
24+
- graphviz=6.0
25+
- pandoc=3.1
26+
# Workflow dependencies: Convert3D
27+
- convert3d=1.3.0
28+
- libitk=5.2 # 5.3 fails with c3d
29+
# Workflow dependencies: FSL (versions pinned in 6.0.6.2)
30+
- fsl-flirt=2111.0
31+
- fsl-fast4=2111.0
32+
- fsl-fugue=2201.2
33+
- fsl-mcflirt=2111.0
34+
- fsl-miscmaths=2203.2
35+
- fsl-topup=2203.1

0 commit comments

Comments
 (0)