Skip to content

Commit c707938

Browse files
authored
Merge pull request #2270 from mgxd/rf/dockerfile
RF: Dockerfile
2 parents a42d929 + 5300fd3 commit c707938

File tree

3 files changed

+148
-62
lines changed

3 files changed

+148
-62
lines changed

.circleci/config.yml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ jobs:
5555
set -e
5656
if [[ "$success" = "0" ]]; then
5757
echo "Pulling from local registry"
58-
docker tag localhost:5000/ubuntu ubuntu:xenial-20200114
58+
docker tag localhost:5000/ubuntu ubuntu:xenial-20200706
5959
docker pull localhost:5000/fmriprep
6060
docker tag localhost:5000/fmriprep nipreps/fmriprep:latest
6161
docker tag localhost:5000/fmriprep nipreps/fmriprep
6262
else
6363
echo "Pulling from Docker Hub"
64-
docker pull ubuntu:xenial-20200114
65-
docker tag ubuntu:xenial-20200114 localhost:5000/ubuntu
64+
docker pull ubuntu:xenial-20200706
65+
docker tag ubuntu:xenial-20200706 localhost:5000/ubuntu
6666
docker push localhost:5000/ubuntu
6767
docker pull nipreps/fmriprep:latest
6868
fi
@@ -1013,14 +1013,14 @@ jobs:
10131013
10141014
test_deploy_pypi:
10151015
docker:
1016-
- image: circleci/python:3.7.4
1016+
- image: circleci/python:3.8.5
10171017
working_directory: /tmp/src/fmriprep
10181018
steps:
10191019
- checkout
10201020
- run:
10211021
name: Build fMRIPrep
10221022
command: |
1023-
pip install --user twine # For use in checking distributions
1023+
python -m pip install --user twine # For use in checking distributions
10241024
THISVERSION=$( python get_version.py )
10251025
THISVERSION=${THISVERSION%.dirty*}
10261026
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
@@ -1029,7 +1029,7 @@ jobs:
10291029
pip install --upgrade "pip>=19.1" numpy
10301030
echo "${CIRCLE_TAG:-$THISVERSION}" > fmriprep/VERSION
10311031
python setup.py sdist
1032-
pip wheel --no-deps -w dist/ .
1032+
python -m pip wheel --no-deps -w dist/ .
10331033
- store_artifacts:
10341034
path: /tmp/src/fmriprep/dist
10351035
- run:
@@ -1038,11 +1038,11 @@ jobs:
10381038
THISVERSION=$( python get_version.py )
10391039
THISVERSION=${THISVERSION%.dirty*}
10401040
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
1041-
twine check dist/fmriprep*.tar.gz
1041+
python -m twine check dist/fmriprep*.tar.gz
10421042
virtualenv --python=python sdist
10431043
source sdist/bin/activate
1044-
pip install --upgrade "pip>=19.1" numpy
1045-
pip install dist/fmriprep*.tar.gz
1044+
python -m pip install --upgrade "pip>=19.1" numpy
1045+
python -m pip install dist/fmriprep*.tar.gz
10461046
which fmriprep | grep sdist\\/bin
10471047
INSTALLED_VERSION=$(fmriprep --version)
10481048
INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'}
@@ -1056,10 +1056,10 @@ jobs:
10561056
THISVERSION=$( python get_version.py )
10571057
THISVERSION=${THISVERSION%.dirty*}
10581058
THISVERSION=${CIRCLE_TAG:-$THISVERSION}
1059-
twine check dist/fmriprep*.whl
1059+
python -m twine check dist/fmriprep*.whl
10601060
virtualenv --python=python wheel
10611061
source wheel/bin/activate
1062-
pip install dist/fmriprep*.whl
1062+
python -m pip install dist/fmriprep*.whl
10631063
which fmriprep | grep wheel\\/bin
10641064
INSTALLED_VERSION=$(fmriprep --version)
10651065
INSTALLED_VERSION=${INSTALLED_VERSION%$'\r'}
@@ -1075,16 +1075,16 @@ jobs:
10751075
cd wrapper
10761076
virtualenv --python=python build
10771077
source build/bin/activate
1078-
pip install --upgrade "pip>=19.1"
1078+
python -m pip install --upgrade "pip>=19.1"
10791079
sed -i -E "s/(__version__ = )'[A-Za-z0-9.-]+'/\1'${CIRCLE_TAG:-$THISVERSION}'/" fmriprep_docker.py
10801080
python setup.py sdist
1081-
pip wheel --no-deps -w dist/ .
1081+
python -m pip wheel --no-deps -w dist/ .
10821082
- store_artifacts:
10831083
path: /tmp/src/fmriprep/wrapper/dist
10841084

10851085
deploy_pypi:
10861086
docker:
1087-
- image: circleci/python:3.7.4
1087+
- image: circleci/python:3.8.5
10881088
working_directory: /tmp/src/fmriprep
10891089
steps:
10901090
- checkout
@@ -1094,26 +1094,26 @@ jobs:
10941094
THISVERSION=$( python get_version.py )
10951095
virtualenv --python=python build
10961096
source build/bin/activate
1097-
pip install --upgrade "pip>=19.1"
1097+
python -m pip install --upgrade "pip>=19.1"
10981098
echo "${CIRCLE_TAG:-$THISVERSION}" > fmriprep/VERSION
10991099
python setup.py sdist
1100-
pip wheel --no-deps -w dist/ .
1100+
python -m pip wheel --no-deps -w dist/ .
11011101
- run:
11021102
name: Build fmriprep-docker
11031103
command: |
11041104
THISVERSION=$( python get_version.py )
11051105
cd wrapper
11061106
virtualenv --python=python build
11071107
source build/bin/activate
1108-
pip install --upgrade "pip>=19.1"
1108+
python -m pip install --upgrade "pip>=19.1"
11091109
sed -i -E "s/(__version__ = )'[A-Za-z0-9.-]+'/\1'${CIRCLE_TAG:-$THISVERSION}'/" fmriprep_docker.py
11101110
python setup.py sdist
1111-
pip wheel --no-deps -w dist/ .
1111+
python -m pip wheel --no-deps -w dist/ .
11121112
- run:
11131113
name: Upload packages to PyPI
11141114
command: |
1115-
pip install --user twine
1116-
twine upload dist/fmriprep* wrapper/dist/fmriprep*
1115+
python -m pip install --user twine
1116+
python -m twine upload dist/fmriprep* wrapper/dist/fmriprep*
11171117
11181118
deployable:
11191119
docker:

Dockerfile

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Use Ubuntu 16.04 LTS
2-
FROM ubuntu:xenial-20200114
2+
FROM ubuntu:xenial-20200706
33

44
# Pre-cache neurodebian key
55
COPY docker/files/neurodebian.gpg /usr/local/etc/neurodebian.gpg
@@ -16,7 +16,7 @@ RUN apt-get update && \
1616
libtool \
1717
pkg-config \
1818
git && \
19-
curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
19+
curl -sSL https://deb.nodesource.com/setup_10.x | bash - && \
2020
apt-get install -y --no-install-recommends \
2121
nodejs && \
2222
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
@@ -47,6 +47,7 @@ RUN curl -sSL https://surfer.nmr.mgh.harvard.edu/pub/dist/freesurfer/6.0.1/frees
4747
--exclude='freesurfer/subjects/V1_average' \
4848
--exclude='freesurfer/trctrain'
4949

50+
# Simulate SetUpFreeSurfer.sh
5051
ENV FSL_DIR="/usr/share/fsl/5.0" \
5152
OS="Linux" \
5253
FS_OVERRIDE=0 \
@@ -64,11 +65,10 @@ ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
6465
MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
6566
PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"
6667

67-
# Installing Neurodebian packages (FSL, AFNI, git)
68+
# Installing Neurodebian packages (FSL, AFNI, git-annex)
6869
RUN curl -sSL "http://neuro.debian.net/lists/$( lsb_release -c | cut -f2 ).us-ca.full" >> /etc/apt/sources.list.d/neurodebian.sources.list && \
6970
apt-key add /usr/local/etc/neurodebian.gpg && \
7071
(apt-key adv --refresh-keys --keyserver hkp://ha.pool.sks-keyservers.net 0xA5D32F012649A5A9 || true)
71-
7272
RUN apt-get update && \
7373
apt-get install -y --no-install-recommends \
7474
fsl-core=5.0.9-5~nd16.04+1 \
@@ -79,37 +79,34 @@ RUN apt-get update && \
7979
git-annex-standalone && \
8080
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
8181

82+
# Setting FSL and AFNI envvars
8283
ENV FSLDIR="/usr/share/fsl/5.0" \
8384
FSLOUTPUTTYPE="NIFTI_GZ" \
8485
FSLMULTIFILEQUIT="TRUE" \
8586
POSSUMDIR="/usr/share/fsl/5.0" \
86-
LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH" \
8787
FSLTCLSH="/usr/bin/tclsh" \
8888
FSLWISH="/usr/bin/wish" \
8989
AFNI_MODELPATH="/usr/lib/afni/models" \
9090
AFNI_IMSAVE_WARNINGS="NO" \
9191
AFNI_TTATLAS_DATASET="/usr/share/afni/atlases" \
92-
AFNI_PLUGINPATH="/usr/lib/afni/plugins"
93-
ENV PATH="/usr/lib/fsl/5.0:/usr/lib/afni/bin:$PATH"
92+
AFNI_PLUGINPATH="/usr/lib/afni/plugins" \
93+
PATH="/usr/lib/fsl/5.0:/usr/lib/afni/bin:$PATH" \
94+
LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH"
9495

9596
# Installing ANTs 2.3.4 (NeuroDocker build)
96-
ENV ANTSPATH=/usr/lib/ants
97-
RUN mkdir -p $ANTSPATH && \
98-
curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
97+
ENV ANTSPATH="/usr/lib/ants" \
98+
PATH="/usr/lib/ants:$PATH"
99+
WORKDIR $ANTSPATH
100+
RUN curl -sSL "https://dl.dropbox.com/s/gwf51ykkk5bifyj/ants-Linux-centos6_x86_64-v2.3.4.tar.gz" \
99101
| tar -xzC $ANTSPATH --strip-components 1
100-
ENV PATH=$ANTSPATH:$PATH
101-
102-
# Installing SVGO
103-
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
104-
RUN apt-get install -y nodejs
105-
RUN npm install -g svgo
106102

107-
# Installing bids-validator
108-
RUN npm install -g bids-validator@1.4.0
103+
# Installing SVGO and bids-validator
104+
RUN npm install -g svgo bids-validator@1.5.4 \
105+
&& rm -rf ~/.npm ~/.empty
109106

110107
# Installing and setting up ICA_AROMA
111-
RUN mkdir -p /opt/ICA-AROMA && \
112-
curl -sSL "https://github.com/oesteban/ICA-AROMA/archive/v0.4.5.tar.gz" \
108+
WORKDIR /opt/ICA-AROMA
109+
RUN curl -sSL "https://github.com/oesteban/ICA-AROMA/archive/v0.4.5.tar.gz" \
113110
| tar -xzC /opt/ICA-AROMA --strip-components 1 && \
114111
chmod +x /opt/ICA-AROMA/ICA_AROMA.py
115112
ENV PATH="/opt/ICA-AROMA:$PATH" \
@@ -122,7 +119,7 @@ RUN curl -sSLO https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_6
122119

123120
# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
124121
ENV PATH="/usr/local/miniconda/bin:$PATH" \
125-
CPATH="/usr/local/miniconda/include/:$CPATH" \
122+
CPATH="/usr/local/miniconda/include:$CPATH" \
126123
LANG="C.UTF-8" \
127124
LC_ALL="C.UTF-8" \
128125
PYTHONNOUSERSITE=1
@@ -144,8 +141,8 @@ RUN conda install -y python=3.7.1 \
144141
zlib; sync && \
145142
chmod -R a+rX /usr/local/miniconda; sync && \
146143
chmod +x /usr/local/miniconda/bin/*; sync && \
147-
conda build purge-all; sync && \
148-
conda clean -tipsy && sync
144+
conda clean -y --all && sync && \
145+
rm -rf ~/.conda ~/.cache/pip/*; sync
149146

150147
# Unless otherwise specified each process should only use one thread - nipype
151148
# will handle parallelization
@@ -163,21 +160,11 @@ RUN python -c "from matplotlib import font_manager" && \
163160

164161
# Precaching atlases
165162
COPY setup.cfg fmriprep-setup.cfg
163+
COPY scripts/fetch_templates.py fetch_templates.py
164+
166165
RUN pip install --no-cache-dir "$( grep templateflow fmriprep-setup.cfg | xargs )" && \
167-
python -c "from templateflow import api as tfapi; \
168-
tfapi.get('MNI152NLin6Asym', resolution=(1, 2), suffix='T1w', desc=None); \
169-
tfapi.get('MNI152NLin6Asym', resolution=(1, 2), desc='brain', suffix='mask'); \
170-
tfapi.get('MNI152NLin2009cAsym', resolution=(1, 2), suffix='T1w', desc=None); \
171-
tfapi.get('MNI152NLin2009cAsym', resolution=(1, 2), desc='brain', suffix='mask'); \
172-
tfapi.get('MNI152NLin2009cAsym', resolution=1, desc='carpet', suffix='dseg'); \
173-
tfapi.get('MNI152NLin2009cAsym', resolution=1, label='brain', suffix='probseg'); \
174-
tfapi.get('MNI152NLin2009cAsym', resolution=2, desc='fMRIPrep', suffix='boldref'); \
175-
tfapi.get('OASIS30ANTs'); \
176-
tfapi.get('fsaverage', density='164k', desc='std', suffix='sphere'); \
177-
tfapi.get('fsaverage', density='164k', desc='vaavg', suffix='midthickness'); \
178-
tfapi.get('fsLR', density='32k'); \
179-
tfapi.get('MNI152NLin6Asym', resolution=2, atlas='HCP', suffix='dseg')" && \
180-
rm fmriprep-setup.cfg && \
166+
python fetch_templates.py && \
167+
rm fmriprep-setup.cfg fetch_templates.py && \
181168
find $HOME/.cache/templateflow -type d -exec chmod go=u {} + && \
182169
find $HOME/.cache/templateflow -type f -exec chmod go=u {} +
183170

@@ -189,18 +176,14 @@ RUN echo "${VERSION}" > /src/fmriprep/fmriprep/VERSION && \
189176
echo "include fmriprep/VERSION" >> /src/fmriprep/MANIFEST.in && \
190177
pip install --no-cache-dir "/src/fmriprep[all]"
191178

192-
RUN install -m 0755 \
193-
/src/fmriprep/scripts/generate_reference_mask.py \
194-
/usr/local/bin/generate_reference_mask
195-
196179
RUN find $HOME -type d -exec chmod go=u {} + && \
197180
find $HOME -type f -exec chmod go=u {} + && \
198181
rm -rf $HOME/.npm $HOME/.conda $HOME/.empty
199182

200183
ENV IS_DOCKER_8395080871=1
201184

202185
RUN ldconfig
203-
WORKDIR /tmp/
186+
WORKDIR /tmp
204187
ENTRYPOINT ["/usr/local/miniconda/bin/fmriprep"]
205188

206189
ARG BUILD_DATE

scripts/fetch_templates.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#!/usr/bin/env python
2+
3+
"Pre-emptive caching of commonly used TemplateFlow templates"
4+
import templateflow.api as tf
5+
6+
7+
def fetch_MNI2009():
8+
"""
9+
Expected templates:
10+
11+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-01_T1w.nii.gz
12+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-02_T1w.nii.gz
13+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-01_desc-brain_mask.nii.gz
14+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-02_desc-brain_mask.nii.gz
15+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-01_desc-carpet_dseg.nii.gz
16+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-02_desc-fMRIPrep_boldref.nii.gz
17+
tpl-MNI152NLin2009cAsym/tpl-MNI152NLin2009cAsym_res-01_label-brain_probseg.nii.gz
18+
"""
19+
template = 'MNI152NLin2009cAsym'
20+
21+
tf.get(template, resolution=(1, 2), desc=None, suffix='T1w')
22+
tf.get(template, resolution=(1, 2), desc='brain', suffix='mask')
23+
tf.get(template, resolution=1, atlas=None, desc='carpet', suffix='dseg')
24+
tf.get(template, resolution=2, desc='fMRIPrep', suffix='boldref')
25+
tf.get(template, resolution=1, label="brain", suffix="probseg")
26+
27+
28+
def fetch_MNI6():
29+
"""
30+
Expected templates:
31+
32+
tpl-MNI152NLin6Asym/tpl-MNI152NLin6Asym_res-01_T1w.nii.gz
33+
tpl-MNI152NLin6Asym/tpl-MNI152NLin6Asym_res-02_T1w.nii.gz
34+
tpl-MNI152NLin6Asym/tpl-MNI152NLin6Asym_res-01_desc-brain_mask.nii.gz
35+
tpl-MNI152NLin6Asym/tpl-MNI152NLin6Asym_res-02_desc-brain_mask.nii.gz
36+
tpl-MNI152NLin6Asym/tpl-MNI152NLin6Asym_res-02_atlas-HCP_dseg.nii.gz
37+
"""
38+
template = 'MNI152NLin6Asym'
39+
40+
tf.get(template, resolution=(1, 2), desc=None, suffix='T1w')
41+
tf.get(template, resolution=(1, 2), desc='brain', suffix='mask')
42+
# CIFTI
43+
tf.get(template, resolution=2, atlas='HCP', suffix='dseg')
44+
45+
46+
def fetch_OASIS():
47+
"""
48+
Expected templates:
49+
50+
tpl-OASIS30ANTs/tpl-OASIS30ANTs_res-01_T1w.nii.gz
51+
tpl-OASIS30ANTs/tpl-OASIS30ANTs_res-01_label-brain_probseg.nii.gz
52+
tpl-OASIS30ANTs/tpl-OASIS30ANTs_res-01_desc-brain_mask.nii.gz
53+
tpl-OASIS30ANTs/tpl-OASIS30ANTs_res-01_desc-BrainCerebellumExtraction_mask.nii.gz
54+
"""
55+
template = "OASIS30ANTs"
56+
57+
tf.get(template, resolution=1, desc=None, label=None, suffix='T1w')
58+
tf.get(template, resolution=1, label='brain', suffix='probseg')
59+
tf.get(template, resolution=1, label='brain', suffix='mask')
60+
tf.get(template, resolution=1, desc='BrainCerebellumExtraction', suffix='mask')
61+
62+
63+
def fetch_fsaverage():
64+
"""
65+
Expected templates:
66+
67+
tpl-fsaverage/tpl-fsaverage_hemi-L_den-164k_desc-std_sphere.surf.gii
68+
tpl-fsaverage/tpl-fsaverage_hemi-R_den-164k_desc-std_sphere.surf.gii
69+
tpl-fsaverage/tpl-fsaverage_hemi-L_den-164k_desc-vaavg_midthickness.shape.gii
70+
tpl-fsaverage/tpl-fsaverage_hemi-R_den-164k_desc-vaavg_midthickness.shape.gii
71+
"""
72+
template = 'fsaverage'
73+
74+
tf.get(template, density='164k', desc='std', suffix='sphere')
75+
tf.get(template, density='164k', desc='vaavg', suffix='midthickness')
76+
77+
78+
def fetch_fsLR():
79+
"""
80+
Expected templates:
81+
82+
tpl-fsLR/tpl-fsLR_hemi-L_den-32k_desc-nomedialwall_dparc.label.gii
83+
tpl-fsLR/tpl-fsLR_hemi-L_den-32k_desc-vaavg_midthickness.shape.gii
84+
tpl-fsLR/tpl-fsLR_hemi-L_den-32k_sphere.surf.gii
85+
tpl-fsLR/tpl-fsLR_hemi-R_den-32k_desc-nomedialwall_dparc.label.gii
86+
tpl-fsLR/tpl-fsLR_hemi-R_den-32k_desc-vaavg_midthickness.shape.gii
87+
tpl-fsLR/tpl-fsLR_hemi-R_den-32k_sphere.surf.gii
88+
tpl-fsLR/tpl-fsLR_space-fsaverage_hemi-L_den-32k_sphere.surf.gii
89+
tpl-fsLR/tpl-fsLR_space-fsaverage_hemi-R_den-32k_sphere.surf.gii
90+
"""
91+
tf.get('fsLR', density='32k')
92+
93+
94+
def main():
95+
fetch_MNI2009()
96+
fetch_MNI6()
97+
fetch_OASIS()
98+
fetch_fsaverage()
99+
fetch_fsLR()
100+
101+
102+
if __name__ == "__main__":
103+
main()

0 commit comments

Comments
 (0)