Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAINT: add docker image/circle build #80

Merged
merged 4 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
version: 2
jobs:
build:
machine:
image: circleci/classic:201808-01
working_directory: /tmp/src/nitransforms
environment:
TZ: "/usr/share/zoneinfo/America/Los_Angeles"
SCRATCH: "/scratch"

steps:
- restore_cache:
keys:
- build-v1-{{ .Branch }}-{{ epoch }}
- build-v1-{{ .Branch }}-
- build-v1-master-
- build-v1-
paths:
- /tmp/docker
- run:
name: Set-up a Docker registry
command: |
docker run -d -p 5000:5000 --restart=always --name=registry \
-v /tmp/docker:/var/lib/registry registry:2
- run:
name: Pull existing images
command: |
set +e
docker pull localhost:5000/ubuntu
success=$?
set -e
if [[ "$success" = "0" ]]; then
echo "Pulling from local registry"
docker tag localhost:5000/ubuntu ubuntu:xenial-20200114
docker pull localhost:5000/nitransforms
docker tag localhost:5000/nitransforms nitransforms:latest
else
echo "Pulling from Docker Hub"
docker pull ubuntu:xenial-20200114
docker tag ubuntu:xenial-20200114 localhost:5000/ubuntu
docker push localhost:5000/ubuntu
fi
- checkout
- run:
name: Build Docker image & push to registry
no_output_timeout: 60m
command: |
e=1 && for i in {1..5}; do
docker build --rm --cache-from=nitransforms:latest \
-t nitransforms:latest \
--build-arg BUILD_DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"` \
--build-arg VCS_REF=`git rev-parse --short HEAD` . \
&& e=0 && break || sleep 15
done && [ "$e" -eq "0" ]
docker tag nitransforms:latest localhost:5000/nitransforms
docker push localhost:5000/nitransforms
- run:
name: Docker registry garbage collection
command: |
docker exec -it registry /bin/registry garbage-collect --delete-untagged \
/etc/docker/registry/config.yml
- save_cache:
key: build-v1-{{ .Branch }}-{{ epoch }}
paths:
- /tmp/docker
- run:
name: Store FreeSurfer license file
command: |
mkdir -p /tmp/fslicense
cd /tmp/fslicense
echo "cHJpbnRmICJrcnp5c3p0b2YuZ29yZ29sZXdza2lAZ21haWwuY29tXG41MTcyXG4gKkN2dW12RVYzelRmZ1xuRlM1Si8yYzFhZ2c0RVxuIiA+IGxpY2Vuc2UudHh0Cg==" | base64 -d | sh
- persist_to_workspace:
root: /tmp
paths:
- fslicense

test_pytest:
machine:
image: circleci/classic:201808-01
environment:
FS_LICENSE: "/tmp/fslicense/license.txt"
working_directory: /tmp/tests
steps:
- attach_workspace:
at: /tmp
- checkout:
path: /tmp/src/nitransforms
- run:
name: Get codecov
command: python -m pip install codecov
- restore_cache:
keys:
- build-v1-{{ .Branch }}-{{ epoch }}
- build-v1-{{ .Branch }}-
- build-v1-master-
- build-v1-
- run:
name: Set-up a Docker registry & pull
command: |
docker run -d -p 5000:5000 --restart=always --name=registry \
-v /tmp/docker:/var/lib/registry registry:2
docker pull localhost:5000/nitransforms
docker tag localhost:5000/nitransforms nitransforms:latest
- run:
name: Run unit tests
no_output_timeout: 2h
command: |
mkdir -p $PWD/artifacts $PWD/summaries
sudo setfacl -d -m group:ubuntu:rwx $PWD
sudo setfacl -m group:ubuntu:rwx $PWD
docker run -u $( id -u ) -it --rm=false -w /src/nitransforms \
-e COVERAGE_FILE=/tmp/summaries/.pytest.coverage \
-v /tmp/fslicense/license.txt:/opt/freesurfer/license.txt:ro \
-v ${PWD}:/tmp nitransforms:latest \
pytest --junit-xml=/tmp/summaries/pytest.xml \
--cov nitransforms --cov-report xml:/tmp/summaries/unittests.xml \
nitransforms/
- run:
name: Submit unit test coverage
command: |
cd /tmp/src/nitransforms
python -m codecov --file /tmp/tests/summaries/unittests.xml \
--flags unittests -e CIRCLE_JOB
- run:
name: Clean up tests directory
when: on_success
command: |
rm -rf /tmp/tests/pytest-of-root
- store_artifacts:
path: /tmp/tests/artifacts

- store_test_results:
path: /tmp/tests/summaries/

test_packaging_and_deploy:
machine:
image: circleci/classic:201808-01
working_directory: /tmp/src/nitransforms
steps:
- checkout
- run: pyenv local 3.7.0
- run:
name: Install build depends
command: python3 -m pip install "setuptools>=30.4.0" "pip>=10.0.1" "twine<2.0" docutils
- run:
name: Build and check
command: |
python3 setup.py check -r -s
python3 setup.py sdist
python3 -m twine check dist/*
- run:
name: Validate version
command: |
THISVERSION=$( python3 get_version.py )
python3 -m pip install dist/*.tar.gz
mkdir empty
cd empty
INSTALLED=$( python3 -c 'import nitransforms; print(nitransforms.__version__)' )
test "${CIRCLE_TAG:-$THISVERSION}" == "$INSTALLED"
- run:
name: Upload to PyPi
command: |
python3 -m twine upload dist/*


workflows:
version: 2
build_test_deploy:
jobs:
- build:
filters:
branches:
ignore:
- /docs?\/.*/
tags:
only: /.*/

- test_pytest:
requires:
- build
filters:
branches:
ignore:
- /docs?\/.*/
- /docker\/.*/
tags:
only: /.*/

- test_packaging_and_deploy:
requires:
- test_pytest
filters:
branches:
ignore: /.*/
tags:
only: /.*/
155 changes: 155 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
FROM ubuntu:xenial-20200114

# Pre-cache neurodebian key
COPY docker/files/neurodebian.gpg /usr/local/etc/neurodebian.gpg

# Prepare environment
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
bzip2 \
ca-certificates \
xvfb \
build-essential \
autoconf \
libtool \
pkg-config \
git && \
curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
apt-get install -y --no-install-recommends \
nodejs && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

# Installing freesurfer
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 | tar zxv --no-same-owner -C /opt \
--exclude='freesurfer/diffusion' \
--exclude='freesurfer/docs' \
--exclude='freesurfer/fsfast' \
--exclude='freesurfer/lib/cuda' \
--exclude='freesurfer/lib/qt' \
--exclude='freesurfer/matlab' \
--exclude='freesurfer/mni/share/man' \
--exclude='freesurfer/subjects/fsaverage_sym' \
--exclude='freesurfer/subjects/fsaverage3' \
--exclude='freesurfer/subjects/fsaverage4' \
--exclude='freesurfer/subjects/cvs_avg35' \
--exclude='freesurfer/subjects/cvs_avg35_inMNI152' \
--exclude='freesurfer/subjects/bert' \
--exclude='freesurfer/subjects/lh.EC_average' \
--exclude='freesurfer/subjects/rh.EC_average' \
--exclude='freesurfer/subjects/sample-*.mgz' \
--exclude='freesurfer/subjects/V1_average' \
--exclude='freesurfer/trctrain'

ENV FSL_DIR="/usr/share/fsl/5.0" \
OS="Linux" \
FS_OVERRIDE=0 \
FIX_VERTEX_AREA="" \
FSF_OUTPUT_FORMAT="nii.gz" \
FREESURFER_HOME="/opt/freesurfer"
ENV SUBJECTS_DIR="$FREESURFER_HOME/subjects" \
FUNCTIONALS_DIR="$FREESURFER_HOME/sessions" \
MNI_DIR="$FREESURFER_HOME/mni" \
LOCAL_DIR="$FREESURFER_HOME/local" \
MINC_BIN_DIR="$FREESURFER_HOME/mni/bin" \
MINC_LIB_DIR="$FREESURFER_HOME/mni/lib" \
MNI_DATAPATH="$FREESURFER_HOME/mni/data"
ENV PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
MNI_PERL5LIB="$MINC_LIB_DIR/perl5/5.8.5" \
PATH="$FREESURFER_HOME/bin:$FSFAST_HOME/bin:$FREESURFER_HOME/tktools:$MINC_BIN_DIR:$PATH"

# Installing Neurodebian packages (FSL, AFNI, git)
RUN curl -sSL "http://neuro.debian.net/lists/$( lsb_release -c | cut -f2 ).us-ca.full" >> /etc/apt/sources.list.d/neurodebian.sources.list && \
apt-key add /usr/local/etc/neurodebian.gpg && \
(apt-key adv --refresh-keys --keyserver hkp://ha.pool.sks-keyservers.net 0xA5D32F012649A5A9 || true)

RUN apt-get update && \
apt-get install -y --no-install-recommends \
fsl-core=5.0.9-5~nd16.04+1 \
fsl-mni152-templates=5.0.7-2 \
afni=16.2.07~dfsg.1-5~nd16.04+1 \
convert3d \
connectome-workbench=1.3.2-2~nd16.04+1 \
git-annex-standalone && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

ENV FSLDIR="/usr/share/fsl/5.0" \
FSLOUTPUTTYPE="NIFTI_GZ" \
FSLMULTIFILEQUIT="TRUE" \
POSSUMDIR="/usr/share/fsl/5.0" \
LD_LIBRARY_PATH="/usr/lib/fsl/5.0:$LD_LIBRARY_PATH" \
FSLTCLSH="/usr/bin/tclsh" \
FSLWISH="/usr/bin/wish" \
AFNI_MODELPATH="/usr/lib/afni/models" \
AFNI_IMSAVE_WARNINGS="NO" \
AFNI_TTATLAS_DATASET="/usr/share/afni/atlases" \
AFNI_PLUGINPATH="/usr/lib/afni/plugins"
ENV PATH="/usr/lib/fsl/5.0:/usr/lib/afni/bin:$PATH"

# Installing ANTs 2.2.0 (NeuroDocker build)
ENV ANTSPATH=/usr/lib/ants
RUN mkdir -p $ANTSPATH && \
curl -sSL "https://dl.dropbox.com/s/2f4sui1z6lcgyek/ANTs-Linux-centos5_x86_64-v2.2.0-0740f91.tar.gz" \
| tar -xzC $ANTSPATH --strip-components 1
ENV PATH=$ANTSPATH:$PATH

# Installing and setting up miniconda
RUN curl -sSLO https://repo.continuum.io/miniconda/Miniconda3-4.5.11-Linux-x86_64.sh && \
bash Miniconda3-4.5.11-Linux-x86_64.sh -b -p /usr/local/miniconda && \
rm Miniconda3-4.5.11-Linux-x86_64.sh

# Set CPATH for packages relying on compiled libs (e.g. indexed_gzip)
ENV PATH="/usr/local/miniconda/bin:$PATH" \
CPATH="/usr/local/miniconda/include/:$CPATH" \
LANG="C.UTF-8" \
LC_ALL="C.UTF-8" \
PYTHONNOUSERSITE=1

# Installing precomputed python packages
RUN conda install -y python=3.7.1 \
pip=19.1 \
mkl=2018.0.3 \
mkl-service \
numpy=1.15.4 \
scipy=1.1.0 \
libxml2=2.9.8 \
libxslt=1.1.32 \
zlib; sync && \
chmod -R a+rX /usr/local/miniconda; sync && \
chmod +x /usr/local/miniconda/bin/*; sync && \
conda build purge-all; sync && \
conda clean -tipsy && sync

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

# Create a shared $HOME directory
RUN useradd -m -s /bin/bash -G users neuro
WORKDIR /home/neuro
ENV HOME="/home/neuro"

# Install package
COPY . /src/nitransforms
ARG VERSION
# Force static versioning within container
RUN echo "${VERSION}" > /src/nitransforms/nitransforms/VERSION && \
echo "include nitransforms/VERSION" >> /src/nitransforms/MANIFEST.in && \
pip install --no-cache-dir "/src/nitransforms[all]"

RUN find $HOME -type d -exec chmod go=u {} + && \
find $HOME -type f -exec chmod go=u {} +


RUN ldconfig
WORKDIR /tmp/

ARG BUILD_DATE
ARG VCS_REF
ARG VERSION
LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.name="nitransforms" \
org.label-schema.vcs-url="https://github.com/poldracklab/nitransforms" \
org.label-schema.version=$VERSION \
org.label-schema.schema-version="1.0"
Loading