diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml index 54e3036..d047151 100644 --- a/.github/workflows/docker-build.yaml +++ b/.github/workflows/docker-build.yaml @@ -5,58 +5,63 @@ on: branches: - main paths: - - 'images/Dockerfile*' + - 'images/**' - '.github/workflows/docker-build.yaml' pull_request: paths: - - 'images/Dockerfile*' + - 'images/**' - '.github/workflows/docker-build.yaml' workflow_dispatch: jobs: - docker-build: + build-dandi: runs-on: ubuntu-latest - strategy: matrix: include: - - tag: latest - dockerfile: Dockerfile - - tag: latest-openscope - dockerfile: Dockerfile.openscope - - tag: latest-allensdk - dockerfile: Dockerfile.allensdk - - tag: latest-gpu - dockerfile: Dockerfile.gpu - - tag: latest-gpu-allensdk - dockerfile: Dockerfile.gpu.allensdk - - tag: latest-matlab - dockerfile: Dockerfile.matlab - + - tag: latest-nebari + build-args: "" + - tag: latest-nebari-gpu + build-args: "BASE_IMAGE=quay.io/nebari/nebari-jupyterlab-gpu:2024.11.1" steps: - - name: Checkout repository - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Log in to Docker Hub + - uses: docker/login-action@v3 if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_DANDIHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_DANDIHUB_TOKEN }} - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + + - uses: docker/build-push-action@v6 + with: + context: ./images/dandi + file: ./images/dandi/Dockerfile + build-args: ${{ matrix.build-args }} + push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} + tags: dandiarchive/dandihub:${{ matrix.tag }} + cache-from: type=registry,ref=dandiarchive/dandihub:${{ matrix.tag }} + cache-to: type=inline + + build-matlab: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: docker/login-action@v3 + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + with: + username: ${{ secrets.DOCKERHUB_DANDIHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_DANDIHUB_TOKEN }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + - uses: docker/setup-buildx-action@v3 - - name: Build and conditionally push Docker Image - uses: docker/build-push-action@v6 + - uses: docker/build-push-action@v6 with: - context: ./images - file: ./images/${{ matrix.dockerfile }} + context: ./images/matlab + file: ./images/matlab/Dockerfile push: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }} - tags: | - ${{ secrets.DOCKERHUB_DANDIHUB_USERNAME }}/dandihub:${{ matrix.tag }} - cache-from: type=registry,ref=${{ secrets.DOCKERHUB_DANDIHUB_USERNAME }}/dandihub:${{ matrix.tag }} + tags: dandiarchive/dandihub:latest-matlab + cache-from: type=registry,ref=dandiarchive/dandihub:latest-matlab cache-to: type=inline diff --git a/images/Dockerfile b/images/Dockerfile deleted file mode 100644 index 0a5cd6b..0000000 --- a/images/Dockerfile +++ /dev/null @@ -1,66 +0,0 @@ -FROM quay.io/jupyter/datascience-notebook:python-3.11.10 - -USER root - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y -qq update \ - && apt-get -y -qq install \ - dbus-x11 \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - tigervnc-standalone-server \ - tigervnc-xorg-extension \ - libnss-wrapper \ - # chown $HOME to workaround that the xorg installation creates a - # /home/jovyan/.cache directory owned by root - && chown -R $NB_UID:$NB_GID $HOME \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir /opt/extras && chown -R $NB_UID:$NB_GID $HOME /opt/extras - -USER $NB_USER - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -RUN df -h && mamba install --yes 'datalad>=0.18' rclone 'h5py>3.3=mpi*' ipykernel zarr blosc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.8/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir -U plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi nibabel nilearn pybids spikeinterface neo itkwidgets \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk 'neuroglancer>=2.28' cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata - -RUN df -h && pip install --no-cache-dir multiscale_spatial_image jupyterlab-git \ - datalad-fuse && \ - rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir brainrender napari diff --git a/images/Dockerfile.allensdk b/images/Dockerfile.allensdk deleted file mode 100644 index 099cb2b..0000000 --- a/images/Dockerfile.allensdk +++ /dev/null @@ -1,72 +0,0 @@ -FROM quay.io/jupyter/datascience-notebook:python-3.11.10 - -USER root - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y -qq update \ - && apt-get -y -qq install \ - dbus-x11 \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - tigervnc-standalone-server \ - tigervnc-xorg-extension \ - libnss-wrapper \ - # chown $HOME to workaround that the xorg installation creates a - # /home/jovyan/.cache directory owned by root - && chown -R $NB_UID:$NB_GID $HOME \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir /opt/extras && chown -R $NB_UID:$NB_GID $HOME /opt/extras - -USER $NB_USER - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -# Install Allen SDK -RUN df -h && mamba create --yes -n allen -c conda-forge python=3.8 pip ipykernel 'h5py>=3.4=mpi*' \ - && /opt/conda/envs/allen/bin/pip install --no-cache-dir allensdk \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && mamba install --yes 'datalad>=0.18' rclone 'h5py>3.3=mpi*' ipykernel zarr blosc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.8/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && /opt/conda/envs/allen/bin/python -m ipykernel install --user --name allen \ - --display-name="Allen SDK" - -RUN df -h && pip install --no-cache-dir -U plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi pybids spikeinterface neo itkwidgets \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata - -RUN df -h && pip install --no-cache-dir multiscale_spatial_image jupyterlab-git \ - datalad-fuse && \ - rm -rf /tmp/* diff --git a/images/Dockerfile.gpu b/images/Dockerfile.gpu deleted file mode 100644 index 7582775..0000000 --- a/images/Dockerfile.gpu +++ /dev/null @@ -1,68 +0,0 @@ -FROM quay.io/jupyter/datascience-notebook:python-3.11.10 - -USER root - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y -qq update \ - && apt-get -y -qq install \ - dbus-x11 \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - tigervnc-standalone-server \ - tigervnc-xorg-extension \ - libnss-wrapper \ - # chown $HOME to workaround that the xorg installation creates a - # /home/jovyan/.cache directory owned by root - && chown -R $NB_UID:$NB_GID $HOME \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir /opt/extras && chown -R $NB_UID:$NB_GID $HOME /opt/extras - -USER $NB_USER - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -RUN df -h && mamba install --yes -c "nvidia/label/cuda-12.6.3" cuda-toolkit cudnn \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy - -RUN df -h && mamba install --yes datalad rclone 'h5py>3.3=mpi*' ipykernel zarr blosc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.8/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir -U plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi nibabel nilearn pybids spikeinterface neo itkwidgets \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk 'neuroglancer>=2.28' cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir multiscale_spatial_image jupyterlab-git \ - datalad-fuse jupyterlab_nvdashboard - -RUN df -h && pip install --no-cache-dir brainrender napari diff --git a/images/Dockerfile.gpu.allensdk b/images/Dockerfile.gpu.allensdk deleted file mode 100644 index 7ee790e..0000000 --- a/images/Dockerfile.gpu.allensdk +++ /dev/null @@ -1,75 +0,0 @@ -FROM quay.io/jupyter/datascience-notebook:python-3.11.10 - -USER root - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y -qq update \ - && apt-get -y -qq install \ - dbus-x11 \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - tigervnc-standalone-server \ - tigervnc-xorg-extension \ - libnss-wrapper \ - # chown $HOME to workaround that the xorg installation creates a - # /home/jovyan/.cache directory owned by root - && chown -R $NB_UID:$NB_GID $HOME \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir /opt/extras && chown -R $NB_UID:$NB_GID $HOME /opt/extras - -USER $NB_USER - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -RUN df -h && mamba install --yes -c "nvidia/label/cuda-11.8.0" cuda-toolkit cudnn \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy - -# Install Allen SDK -RUN df -h && mamba create --yes -n allen -c conda-forge python=3.11 pip ipykernel 'h5py>=3.4=mpi*' \ - && /opt/conda/envs/allen/bin/pip install --no-cache-dir allensdk \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && mamba install --yes datalad rclone 'h5py>3.3=mpi*' ipykernel zarr blosc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.8/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && /opt/conda/envs/allen/bin/python -m ipykernel install --user --name allen \ - --display-name="Allen SDK" - -RUN df -h && pip install --no-cache-dir -U plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi pybids spikeinterface neo itkwidgets \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir multiscale_spatial_image jupyterlab-git \ - datalad-fuse jupyterlab_nvdashboard && \ - rm -rf /tmp/* diff --git a/images/Dockerfile.gpu.matlab b/images/Dockerfile.gpu.matlab deleted file mode 100644 index e82669b..0000000 --- a/images/Dockerfile.gpu.matlab +++ /dev/null @@ -1,176 +0,0 @@ -ARG MATLAB_RELEASE=r2023a -FROM --platform=linux/amd64 ghcr.io/mathworks-ref-arch/matlab-integration-for-jupyter/jupyter-byoi-matlab-notebook:${MATLAB_RELEASE} - -USER root -ARG VERSION="1.1.5" - -ARG EXTRA_DIR=/opt/extras - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - uidmap squashfs-tools squashfuse fuse2fs fuse-overlayfs fakeroot \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - git build-essential \ - && rm -rf /tmp/* /var/lib/apt/lists/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" | sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y update \ - && apt-get install -y \ - dbus-x11 \ - libgl1-mesa-glx \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - libnss-wrapper \ - && rm -rf /tmp/* /var/lib/apt/lists/* - -# Remove light-locker to prevent screen lock -ARG TURBOVNC_VERSION=3.0.2 -RUN df -h && wget -q "https://sourceforge.net/projects/turbovnc/files/${TURBOVNC_VERSION}/turbovnc_${TURBOVNC_VERSION}_amd64.deb/download" -O turbovnc_${TURBOVNC_VERSION}_amd64.deb && \ - apt-get install -y -q ./turbovnc_${TURBOVNC_VERSION}_amd64.deb && \ - apt-get remove -y -q light-locker && \ - rm ./turbovnc_${TURBOVNC_VERSION}_amd64.deb && \ - ln -s /opt/TurboVNC/bin/* /usr/local/bin/ \ - && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir ${EXTRA_DIR} && chown -R $NB_UID:$NB_GID $HOME ${EXTRA_DIR} - -USER $NB_USER - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -# Install CUDA toolkit and extension for GPU usage display -RUN df -h && CONDA_OVERRIDE_CUDA="12.3" mamba install --yes -c "nvidia/label/cuda-12.3.0" cuda-toolkit cudnn \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy jupyterlab_nvdashboard - -# RUN echo -e "\n\ -# import os \n\ -# os.environ['LD_LIBRARY_PATH'] = '/usr/local/nvidia/lib64' \n\ -# c.Spawner.env.update('LD_LIBRARY_PATH') \n\ -# " >> ~/.jupyter/jupyter_notebook_config.py - -RUN df -h && mamba install --yes datalad rclone 'h5py>3.3=mpi*' ipykernel zarr blosc gcc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.7/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi nibabel nilearn pybids spikeinterface neo \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk 'neuroglancer>=2.28' cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata "tensorflow[and-cuda]==2.14" - -# Ensure OpenSSL is up-to-date -RUN df -h && pip install -U pyopenssl && \ - rm -rf /tmp/* - -# Install the jupyter-matlab kernel and matlab-proxy -RUN df -h && pip install --no-cache-dir jupyter-matlab-proxy && \ - rm -rf /tmp/* - -# Install the required Toolboxes with user root -# Optimization toolbox is a required dependency -USER root -ARG MATLAB_RELEASE -ARG TOOLBOXES="Bioinformatics_Toolbox \ - Computer_Vision_Toolbox \ - Curve_Fitting_Toolbox \ - Deep_Learning_Toolbox \ - Econometrics_Toolbox \ - Image_Processing_Toolbox \ - Optimization_Toolbox \ - Statistics_and_Machine_Learning_Toolbox \ - Signal_Processing_Toolbox \ - Parallel_Computing_Toolbox \ - Financial_Toolbox \ - Wavelet_Toolbox \ - Deep_Learning_Toolbox_Converter_for_TensorFlow_models" -RUN df -h && wget -q https://www.mathworks.com/mpm/glnxa64/mpm && \ - chmod +x mpm -RUN df -h && ./mpm install \ - --release=${MATLAB_RELEASE} \ - --destination=/opt/matlab \ - --products ${TOOLBOXES} && \ - rm -f mpm /tmp/mathworks_root.log - -# Switch back to NB_USER for addons and live-scripts installations -USER $NB_USER - -## Adds add-ons and register them in the Matlab instance -# Patch startup.m to automatically register the addons -# The registration process simply iterate over all entries from the ADDONS_DIR folder -# and add them to the "path" -ARG ADDONS_DIR=${EXTRA_DIR}/dandi -ARG STARTUP_SCRIPT=/opt/conda/lib/python3.10/site-packages/matlab_proxy/matlab/startup.m - -# Install the live-scripts examples -# RUN git clone https://github.com/INCF/example-live-scripts ${ADDONS_DIR}/example-live-scripts - -RUN df -h && echo -e "\n\ -% Sets the number of workers for 'Processes' to 5\n\ -cluster = parcluster('Processes'); \n\ -cluster.NumWorkers = 5; \n\ -saveProfile(cluster); \n\ - \n\ -% Copy the live-example folder \n\ -homedirExamples = strcat(getenv('HOME'), '/example-live-scripts') \n\ -if not(isfolder(homedirExamples)) \n\ - % copyfile('${ADDONS_DIR}/example-live-scripts', homedirExamples) \n\ - % repo = gitclone('https://github.com/INCF/example-live-scripts', homedirExamples, Depth=1); \n\ - system(strcat(string('git clone --depth=1 https://github.com/INCF/example-live-scripts '), homedirExamples)) \n\ -end \n\ -% Adds the addons to the path \n\ -addons = dir('${ADDONS_DIR}'); \n\ -addons = setdiff({addons([addons.isdir]).name}, {'.', '..'}); \n\ -for addon_idx = 1:numel(addons) \n\ - addpath(genpath(strcat('${ADDONS_DIR}/', addons{addon_idx}))); \n\ -end \n\ -generateCore(); % Generate the most recent nwb-schema \n\ -% ciapkg.io.loadDependencies('guiEnabled', 0); % Load dependencies for CIAtah \n\ -% ADD HERE EXTRA ACTIONS FOR YOUR ADD-ON IF REQUIRED! \n\ -clear" >> ${STARTUP_SCRIPT} - -# Variables for addons management that are tied to a specific release -ARG ADDONS_RELEASES="https://github.com/NeurodataWithoutBorders/matnwb/archive/refs/tags/v2.6.0.2.zip \ - https://github.com/schnitzer-lab/EXTRACT-public/archive/refs/heads/master.zip \ - https://github.com/bahanonu/ciatah/archive/refs/heads/master.zip" - -# Add add-ons for Dandi: create the addons folder and download/unzip the addons -RUN df -h && mkdir -p ${ADDONS_DIR} && \ - cd ${ADDONS_DIR} && \ - for addon in $ADDONS_RELEASES; do \ - wget -O addon.zip $addon \ - && unzip addon.zip \ - && rm addon.zip; \ - done - -# Variables for addons management that always takes the last release -ARG ADDONS_LATEST="https://github.com/emeyers/Brain-Observatory-Toolbox" - -# Add add-ons for Dandi: detect/download/unzip the last release version -RUN df -h && cd ${ADDONS_DIR} && \ - for addon in $ADDONS_LATEST; do \ - wget -O addon.zip $(echo "$addon/releases/latest" | sed 's/\/github.com\//\/api.github.com\/repos\//' | xargs wget -qO- | grep zipball_url | cut -d '"' -f 4) \ - && unzip addon.zip \ - && rm addon.zip; \ - done diff --git a/images/Dockerfile.openscope b/images/Dockerfile.openscope deleted file mode 100644 index 6cd8a89..0000000 --- a/images/Dockerfile.openscope +++ /dev/null @@ -1,77 +0,0 @@ -FROM quay.io/jupyter/datascience-notebook:python-3.11.10 - -USER root - -RUN df -h && apt update \ - && apt install -y software-properties-common \ - && add-apt-repository -y 'ppa:apptainer/ppa' \ - && apt update \ - && apt install -y apptainer-suid \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && apt-get update && apt-get install -y ca-certificates libseccomp2 \ - s3fs netbase less parallel tmux screen vim emacs htop curl \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -RUN df -h && curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ - -o "awscliv2.zip" && unzip awscliv2.zip \ - && ./aws/install && rm -rf ./aws awscliv2.zip - -# Install jupyter server proxy and desktop -RUN df -h && curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg \ - && echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list \ - && apt-get -y -qq update \ - && apt-get -y -qq install \ - dbus-x11 \ - xfce4 \ - xfce4-panel \ - xfce4-session \ - xfce4-settings \ - xorg \ - xubuntu-icon-theme \ - brave-browser \ - tigervnc-standalone-server \ - tigervnc-xorg-extension \ - libnss-wrapper \ - # chown $HOME to workaround that the xorg installation creates a - # /home/jovyan/.cache directory owned by root - && chown -R $NB_UID:$NB_GID $HOME \ - && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/* - -# apt-get may result in root-owned directories/files under $HOME -RUN df -h && mkdir /opt/extras && chown -R $NB_UID:$NB_GID $HOME /opt/extras - -USER $NB_USER - -RUN df -h && pip install --no-cache-dir jupyter-remote-desktop-proxy - -ENV MAMBA_NO_LOW_SPEED_LIMIT=1 - -RUN df -h && mamba install --yes 'datalad>=0.18' rclone 'h5py>3.3=mpi*' ipykernel zarr blosc eccodes websockify \ - && wget --quiet https://raw.githubusercontent.com/DanielDent/git-annex-remote-rclone/v0.8/git-annex-remote-rclone \ - && chmod +x git-annex-remote-rclone && mv git-annex-remote-rclone /opt/conda/bin \ - && conda clean --all -f -y && rm -rf /tmp/* - -RUN df -h && pip install --no-cache-dir -U plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi nibabel nilearn pybids spikeinterface neo itkwidgets \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk 'neuroglancer>=2.28' cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata - -RUN df -h && pip install --no-cache-dir multiscale_spatial_image jupyterlab-git \ - datalad-fuse - -RUN df -h && pip install --no-cache-dir brainrender napari - -# Leaving "standard" Dockerfile copy above as-is to simplify later switch to modular builds. -USER root - -RUN df -h && apt-get install -y coreutils libgl1 libglx-mesa0 libglib2.0-0 && rm -rf /var/lib/apt/lists/* /tmp/* - -USER $NB_USER - -RUN df -h && cd /tmp \ - && git clone --filter='blob:none' https://github.com/AllenInstitute/openscope_databook.git \ - && pip install --no-cache-dir -e './openscope_databook[dev]' \ - && rm -rf /tmp/* diff --git a/images/README.md b/images/README.md index 3302983..096ba62 100644 --- a/images/README.md +++ b/images/README.md @@ -1,106 +1,51 @@ -# Dandi Docker Images +# DANDI Docker Images -This folder contains Dockerfiles to build various Docker images for Dandi: +Docker images for DandiHub (Nebari-based JupyterHub deployment). -* `Dockerfile` and `Dockerfile.gpu` provide Jupyter(R) notebooks for datascience. The `Dockerfile.gpu` enables the use of GPU. -* `Dockerfile.matlab` provides a jupyter environment with MATLAB(R) installed. This image requires you to bring your own licence. +These images extend upstream [Nebari](https://nebari.dev) images with DANDI-specific tools. -## MATLAB Docker Image +## Images -The MATLAB Docker image relies on the [MATLAB Integration for Jupyter in a Docker Container](https://github.com/mathworks-ref-arch/matlab-integration-for-jupyter). -It is shipped with [MATLAB-proxy](https://github.com/mathworks/matlab-proxy) which enables communication with MATLAB from a web-browser, and with [MATLAB-proxy-jupyter](https://github.com/mathworks/jupyter-matlab-proxy) which adds MATLAB integration for Jupyter. +| Image | Base | Description | +|-------|------|-------------| +| `dandiarchive/dandihub:latest-nebari` | nebari-jupyterlab | CPU | +| `dandiarchive/dandihub:latest-nebari-gpu` | nebari-jupyterlab-gpu | GPU/CUDA | +| `dandiarchive/dandihub:latest-matlab` | matlab-integration-for-jupyter | MATLAB | -This Dockerfile includes the following add-ons: +## dandi/ -* matnwb v2.6.0.0 -* Brain-Observatory-Toolbox v0.9.2 +Extends Nebari jupyterlab with: +- AWS CLI (S3 access for DANDI data) +- rclone + datalad (dataset management) +- git-annex-remote-rclone -### How to Build +## matlab/ -Building the MATLAB Docker image is straight forward. -The following lines consider that you already cloned the repository and that you are positioned in the `docker` folder in the cloned repository on your file system. +MATLAB integration for Nebari with: +- Cleared ENTRYPOINT for Nebari compatibility +- libnss-wrapper for user identity handling +- MATLAB licensing via matlab-proxy -```bash -docker build -t dandi-matlab - < Dockerfile.matlab -``` - -This will build the image tagging it as `dandi-matlab`. - -### How to Run +**Note:** MATLAB requires users to provide their own license. -Running a container for the built image requires that a port is passed to the command line to tell the container which internal port needs to be exposed and on which port to map it in the host system. +## Local Build ```bash -docker run -p 8888:8888 dandi-matlab:latest -``` - -This command considers the exposition of port `8888` and maps it to the port `8888` in the host. -The syntax of the option is `-p [host port]:[container port]`. -The port to expose in the container is always `8888`, but the host port can be changed to what is the best for your system. +# dandi CPU +docker build -t dandihub:latest-nebari -f images/dandi/Dockerfile images/dandi -After the container started, you can check the logs and you will see lines giving you the address you can open in your web browser to start the Jupyter instance. +# dandi GPU +docker build \ + --build-arg BASE_IMAGE=quay.io/nebari/nebari-jupyterlab-gpu:2024.11.1 \ + -t dandihub:latest-nebari-gpu \ + -f images/dandi/Dockerfile images/dandi +# matlab +docker build -t dandihub:latest-matlab -f images/matlab/Dockerfile images/matlab ``` -To access the server, open this file in a browser: - file:///home/jovyan/.local/share/jupyter/runtime/jpserver-6-open.html -Or copy and paste one of these URLs: - http://78bd0f342a19:8888/lab?token=6bf3ad4d468ab3532fab610f5ff28dcf27b1b60300ec8e0c - or http://127.0.0.1:8888/lab?token=6bf3ad4d468ab3532fab610f5ff28dcf27b1b60300ec8e0c -``` - -To open locally the Jupyter, copy/paste the `127.0.0.1:8888/xxxxx` address in your browser. - -CAUTION: If you changed the port on which will be mapped the internal container port, do not forget to change it also in the address you copy/paste from the logs. - -### Closing your Session - -Be careful while closing your session. -If you don't close the session properly prior to stop your container, _i.e_: closing the MATLAB session and disconnecting yourself, there is chances that the MATLAB licencing system sees yourself as still connected and you'll have to wait the timeout of the session to be able to log/connect again after restarting the container. - -To properly close your session, click on the `MATLAB Jupyter Setting` button which appears above the MATLAB top bar. -From there, if you really want to close your session, clic on "Stop MATLAB Session", and if you really want to stop your Jupyter session, clic on "Sign Out". - -### Add new Add-Ons - -By default, the `Dockerfile.matlab` image is shipped with two addons already installed and accessible from MATLAB. -You can easily add/remove addons by changing some lines in the Dockerfile: the addons links to download/install are defined by the `ARG ADDONS` variable. - -CAUTION: The download links have to be release links towards `.zip` files. - -#### How the Add-On Registration is Working - -The add-ons registration is actually performed in two steps happening at two differents times: at "docker image construction" time, and at MATLAB startup time. - -During the docker image construction, all add-ons referenced by the `ADDONS` variable in the Dockerfile are downloaded and extracted in a specific folder: `/opt/extras/dandi`. - -At startup-time, this folder is automatically scanned by MATLAB and all downloaded add-ons are added to the "path" of MATLAB. -The code responsible for the auto-scan of the add-ons folder is directly injected in the `startup.m` file during the docker image construction. -If some add-ons require extra actions after being installed/added to the path, you can modify these lines to add extra action before the `clear`: - -```dockerfile -RUN echo -e "\n\ -addons = dir('${ADDONS_DIR}'); \n\ -addons = setdiff({addons([addons.isdir]).name}, {'.', '..'}); \n\ -for addon_idx = 1:numel(addons) \n\ - addpath(strcat('${ADDONS_DIR}/', addons{addon_idx})); \n\ -end \n\ -generateCore(); % Generate the most recent nwb-schema \n\ -% ADD HERE EXTRA ACTIONS FOR YOUR ADD-ON IF REQUIRED! \n\ -clear" >> /opt/conda/lib/python3.10/site-packages/matlab_proxy/matlab/startup.m -``` - -### Customize your Container - -You can customize some parameter of your container changing some variables in the `Dockerfile.matlab`. - -You can impact those parameters: - -`ADDONS_DIR`: -This variable defines where the add-ons must be downloaded/extracted and what will be the folder scanned by MATLAB at startup time. -If you change this folder, the Jupyter user needs to have read/write access to it. This comes from a specificity of `matnwb` which requires the execution of some extra actions for its activation. -`ADDONS_RELEASE`: -This variable defines the list of add-ons to download and install. You can add as much add-ons as you want as long as they are compatible with MATLAB-R22. +## CI -`ADDONS_LATEST`: -This variable defines the list of add-ons to download and install directly from the lastest version identified in the github repository. \ No newline at end of file +The `docker-build.yaml` workflow: +- Builds on PR (no push) - validates changes +- Pushes to Docker Hub on merge to main diff --git a/images/dandi/Dockerfile b/images/dandi/Dockerfile new file mode 100644 index 0000000..047a8e6 --- /dev/null +++ b/images/dandi/Dockerfile @@ -0,0 +1,23 @@ +ARG BASE_IMAGE=quay.io/nebari/nebari-jupyterlab:2024.11.1 +FROM ${BASE_IMAGE} + +# AWS CLI - for S3 access (DANDI data lives on S3) +RUN curl --silent --show-error "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" \ + -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install \ + && rm -rf ./aws awscliv2.zip + +# dandi conda deps (rclone for cloud storage, datalad for dataset management) +COPY environment.yaml /opt/dandi/environment.yaml +RUN /opt/scripts/install-conda-environment.sh /opt/dandi/environment.yaml 'false' + +# git-annex-remote-rclone - bridge between git-annex and rclone +# TODO: pin to a specific commit/tag for reproducibility +RUN wget --quiet https://github.com/git-annex-remote-rclone/git-annex-remote-rclone/raw/refs/heads/master/git-annex-remote-rclone \ + && chmod +x git-annex-remote-rclone \ + && mv git-annex-remote-rclone /opt/conda/bin + +# fix permissions for multi-user environment +COPY postBuild /opt/dandi/postBuild +RUN /opt/dandi/postBuild diff --git a/images/dandi/environment.yaml b/images/dandi/environment.yaml new file mode 100644 index 0000000..3471868 --- /dev/null +++ b/images/dandi/environment.yaml @@ -0,0 +1,8 @@ +name: default +channels: + - conda-forge +dependencies: + - pip + - rclone + - pip: + - datalad diff --git a/images/dandi/postBuild b/images/dandi/postBuild new file mode 100755 index 0000000..fdceda7 --- /dev/null +++ b/images/dandi/postBuild @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail +set -x + + +# if DEFAULT_ENV is unset ${DEFAULT_ENV+x} expands to nothing otherwise +# it substitutes the string x. This allows us to check if the variable +# is set without triggering an unbound variable error +if [[ -z "${DEFAULT_ENV+x}" ]]; then + fix-permissions /opt/conda/bin +else + fix-permissions "/opt/conda/envs/${DEFAULT_ENV}" +fi diff --git a/images/Dockerfile.matlab b/images/matlab/Dockerfile similarity index 70% rename from images/Dockerfile.matlab rename to images/matlab/Dockerfile index 32f87cc..fa6d2a0 100644 --- a/images/Dockerfile.matlab +++ b/images/matlab/Dockerfile @@ -1,13 +1,12 @@ -ARG MATLAB_RELEASE=r2024b -FROM --platform=linux/amd64 ghcr.io/mathworks-ref-arch/matlab-integration-for-jupyter/jupyter-matlab-notebook:${MATLAB_RELEASE} +ARG MATLAB_RELEASE=r2025b +FROM ghcr.io/mathworks-ref-arch/matlab-integration-for-jupyter/jupyter-matlab-notebook:${MATLAB_RELEASE} USER root -# install extra apps, add extra folder and fix ownership in case apt-get messed with it +# install extra apps, add extra folder and fix ownership in case apt messed with it ARG EXTRA_DIR=/opt/extras -RUN df -h && apt-get update \ - && apt-get install -y \ - htop \ +RUN apt update \ + && apt install -y --no-install-recommends \ libnss-wrapper \ curl \ git \ @@ -16,13 +15,10 @@ RUN df -h && apt-get update \ && mkdir ${EXTRA_DIR} \ && chown -R $NB_UID:$NB_GID $HOME ${EXTRA_DIR} -RUN df -h && pip install --no-cache-dir datalad 'h5py>3.3' zarr pyopenssl plotly jupyter_bokeh jupytext nbgitpuller datalad_container \ - datalad-osf dandi nibabel nilearn pybids spikeinterface neo \ - 'pydra>=0.25' 'pynwb>=2.8.3' 'nwbwidgets>=0.10.2' hdf5plugin s3fs h5netcdf "xarray[io]" \ - aicsimageio kerchunk 'neuroglancer>=2.28' cloud-volume ipywidgets ome-zarr \ - webio_jupyter_extension https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip \ - tensorstore anndata tensorflow && \ - rm -rf /tmp/* +COPY matlab-requirements.txt /tmp/requirements.txt +RUN pip install --no-cache-dir -r /tmp/requirements.txt \ + && pip install --no-cache-dir https://github.com/balbasty/dandi-io/archive/refs/heads/main.zip --no-deps && \ + rm -rf /tmp/* # Install the required Toolboxes with user root # Optimization toolbox is a required dependency @@ -32,15 +28,15 @@ ARG TOOLBOXES="Bioinformatics_Toolbox \ Curve_Fitting_Toolbox \ Deep_Learning_Toolbox \ Econometrics_Toolbox \ + Financial_Toolbox \ Image_Processing_Toolbox \ - Optimization_Toolbox \ - Statistics_and_Machine_Learning_Toolbox \ - Signal_Processing_Toolbox \ Parallel_Computing_Toolbox \ - Financial_Toolbox \ + Signal_Processing_Toolbox \ + Statistics_and_Machine_Learning_Toolbox \ Wavelet_Toolbox \ + Optimization_Toolbox \ Deep_Learning_Toolbox_Converter_for_TensorFlow_models" -RUN df -h && wget -q https://www.mathworks.com/mpm/glnxa64/mpm && \ +RUN wget -q https://www.mathworks.com/mpm/glnxa64/mpm && \ chmod +x mpm && \ ./mpm install \ --release=${MATLAB_RELEASE} \ @@ -48,18 +44,18 @@ RUN df -h && wget -q https://www.mathworks.com/mpm/glnxa64/mpm && \ --products ${TOOLBOXES} && \ rm -f mpm /tmp/mathworks_root.log -# Switch to NB_USER for addons and live-scripts installations -USER $NB_USER +# Switch to NB_UID for addons and live-scripts installations +USER $NB_UID ## Adds add-ons and register them in the Matlab instance # Patch startup.m to automatically register the addons # The registration process simply iterate over all entries from the ADDONS_DIR folder # and add them to the "path" ARG ADDONS_DIR=${EXTRA_DIR}/dandi -ARG STARTUP_SCRIPT=/opt/conda/lib/python3.11/site-packages/matlab_proxy/matlab/startup.m +ARG STARTUP_SCRIPT=/opt/conda/lib/python3.13/site-packages/matlab_proxy/matlab/startup.m # Generate MATLAB startup script -RUN df -h && echo -e "\n\ +RUN echo -e "\n\ % Set the number of workers for 'Processes' to 5\n\ cluster = parcluster('Processes'); \n\ cluster.NumWorkers = 5; \n\ @@ -83,13 +79,13 @@ end \n\ % ADD HERE EXTRA ACTIONS FOR YOUR ADD-ON IF REQUIRED! \n\ clear" >> ${STARTUP_SCRIPT} -# Variables for addons management that are tied to a specific release or commit -ARG ADDONS_RELEASES="https://github.com/NeurodataWithoutBorders/matnwb/archive/2c3a4e13c9504724c08f3d937c08c730accf7685.zip \ - https://github.com/schnitzer-lab/EXTRACT-public/archive/refs/heads/master.zip \ - https://github.com/bahanonu/ciatah/archive/refs/heads/master.zip" +# Variables for addons management that are tied to a specific release, commit or bleeding edge +ARG ADDONS_RELEASES="https://github.com/schnitzer-lab/EXTRACT-public/archive/refs/heads/master.zip \ + https://github.com/bahanonu/ciatah/archive/refs/heads/master.zip \ + https://github.com/NeurodataWithoutBorders/matnwb/archive/refs/tags/2.9.0.zip" # Add add-ons for Dandi: create the addons folder and download/unzip the addons -RUN df -h && mkdir -p ${ADDONS_DIR} && \ +RUN mkdir -p ${ADDONS_DIR} && \ cd ${ADDONS_DIR} && \ for addon in $ADDONS_RELEASES; do \ wget -O addon.zip $addon \ @@ -98,12 +94,17 @@ RUN df -h && mkdir -p ${ADDONS_DIR} && \ done # Variables for addons management that always takes the last release -ARG ADDONS_LATEST="https://github.com/emeyers/Brain-Observatory-Toolbox" +ARG ADDONS_LATEST="https://github.com/MATLAB-Community-Toolboxes-at-INCF/Brain-Observatory-Toolbox \ + https://github.com/MATLAB-Community-Toolboxes-at-INCF/DeepInterpolation-MATLAB" # Add add-ons for Dandi: detect/download/unzip the last release version -RUN df -h && cd ${ADDONS_DIR} && \ +RUN cd ${ADDONS_DIR} && \ for addon in $ADDONS_LATEST; do \ wget -O addon.zip $(echo "$addon/releases/latest" | sed 's/\/github.com\//\/api.github.com\/repos\//' | xargs wget -qO- | grep zipball_url | cut -d '"' -f 4) \ && unzip addon.zip \ && rm addon.zip; \ done + +# Clear the ENTRYPOINT so Nebari can control startup +ENTRYPOINT [] +CMD ["/bin/bash"] diff --git a/images/matlab/matlab-requirements.txt b/images/matlab/matlab-requirements.txt new file mode 100644 index 0000000..5549dda --- /dev/null +++ b/images/matlab/matlab-requirements.txt @@ -0,0 +1,38 @@ +# required by the Deep Learning Toolbox Converter for TensorFlow models +tensorstore +tensorflow + +# required for dandi-io +datalad_container +dandi +datalad-osf +datalad +lxml +xmlschema + +# pyopenssl +# plotly +# jupyter_bokeh +# jupytext +# nbgitpuller +# nibabel +# nilearn +# pybids +# spikeinterface +# neo +# pydra>=0.25 +# nwbwidgets>=0.10.2 +# s3fs +# h5netcdf +# xarray[io] +# kerchunk +# neuroglancer>=2.28 +# cloud-volume +# ipywidgets +# webio_jupyter_extension +# anndata +# pynwb +# h5py +# hdf5plugin +# ome-zarr +# zarr