diff --git a/appendix b/appendix index 80c071c..1e0e3d3 100644 --- a/appendix +++ b/appendix @@ -39,20 +39,54 @@ RUN rm -rf ${REPO_DIR}/book ${REPO_DIR}/docs # Convert NB_USER to ENV (from ARG) so that it passes to the child dockerfile ENV NB_USER=${NB_USER} -## ONBUILD section. These are run in child Dockerfiles. First thing that is run +## ONBUILD section. These are run in child Dockerfiles. These are run right after the FROM image is loaded ONBUILD USER ${NB_USER} # ${REPO_DIR} is owned by ${NB_USER} ONBUILD COPY --chown=${NB_USER}:${NB_USER} . ${REPO_DIR}/childimage +# repo2docker will load files from a .binder or binder directory if +# present. We check if those directories exist. +ONBUILD RUN echo "Checking for 'binder' or '.binder' subfolder" \ + ; cd "${REPO_DIR}/childimage/" \ + ; if [ -d binder ] ; then \ + echo "Using 'binder/' build context" \ + ; elif [ -d .binder ] ; then \ + echo "Using '.binder/' build context" \ + ; else \ + echo "Using './' build context" \ + ; fi + # Copy Desktop files into ${REPO_DIR}/Desktop if they exist. start will copy to Application dir and Desktop -ONBUILD RUN if [ -d ${REPO_DIR}/childimage/Desktop ]; then \ - mkdir -p ${REPO_DIR}/Desktop && \ - cp -r ${REPO_DIR}/childimage/Desktop/* ${REPO_DIR}/Desktop/; \ - fi +# Will not fail if Desktop dir exists but is empty +ONBUILD RUN echo "Checking for 'Desktop directory'..." \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder \ + ; [ -d .binder ] && cd .binder \ + ; if test -d Desktop ; then \ + mkdir -p "${REPO_DIR}/Desktop" && \ + [ "$(ls -A Desktop 2>/dev/null)" ] && cp -r Desktop/* "${REPO_DIR}/Desktop/"; \ + fi + +# Install apt packages specified in a apt.txt file if it exists. +# blank lines and comments are supported in apt.txt +ONBUILD USER root +ONBUILD RUN echo "Checking for 'apt.txt'..." \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder \ + ; [ -d .binder ] && cd .binder \ + ; if test -f "apt.txt" ; then \ + package_list=$(grep -v '^\s*#' apt.txt | grep -v '^\s*$' | sed 's/\r//g; s/#.*//; s/^[[:space:]]*//; s/[[:space:]]*$//' | awk '{$1=$1};1') \ + && apt-get update --fix-missing > /dev/null \ + && apt-get install --yes --no-install-recommends $package_list \ + && apt-get autoremove --purge \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + ; fi +ONBUILD USER ${NB_USER} -# Add the environment +# Add the conda environment # sometimes package solving will get rid of pip installed packages. Make sure jupyter-remote-desktop-proxy does not disappear ONBUILD RUN echo "Checking for 'conda-lock.yml' or 'environment.yml'..." \ ; cd "${REPO_DIR}/childimage/" \ @@ -72,6 +106,54 @@ ONBUILD RUN echo "Checking for 'conda-lock.yml' or 'environment.yml'..." \ find ${NB_PYTHON_PREFIX}/lib/python*/site-packages/bokeh/server/static -follow -type f -name '*.js' ! -name '*.min.js' -delete \ ; fi +# If a requirements.txt file exists, use pip to install packages +# listed there. We don't want to save cached wheels in the image +# to avoid wasting space. +ONBUILD RUN echo "Checking for pip 'requirements.txt'..." \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder \ + ; [ -d .binder ] && cd .binder \ + ; if test -f "requirements.txt" ; then \ + ${NB_PYTHON_PREFIX}/bin/pip install --no-cache -r requirements.txt \ + ; fi + +# Add the r packages +ONBUILD RUN echo "Checking for 'install.R" \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder \ + ; [ -d .binder ] && cd .binder \ + ; if test -f "install.R" ; then echo "Using install.R" & \ + Rscript install.R \ + ; fi + +# If a start file exists, put that under ${REPO_DIR}/childimage/start. +# This is sourced in ${REPO_DIR}/start +ONBUILD RUN echo "Checking for 'start'..." \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder && cp start ${REPO_DIR}/childimage/start \ + ; [ -d .binder ] && cd .binder && cp start ${REPO_DIR}/childimage/start \ + ; if test -f "start" ; then \ + chmod +x start \ + ; fi + +# If a postBuild file exists, run it! +# After it's done, we try to remove any possible cruft commands there +# left behind under $HOME - particularly stuff that jupyterlab extensions +# leave behind. +ONBUILD RUN echo "Checking for 'postBuild'..." \ + ; cd "${REPO_DIR}/childimage/" \ + ; [ -d binder ] && cd binder \ + ; [ -d .binder ] && cd .binder \ + ; if test -f "postBuild" ; then \ + chmod +x postBuild \ + && ./postBuild \ + && rm -rf /tmp/* \ + && rm -rf ${HOME}/.cache ${HOME}/.npm ${HOME}/.yarn \ + && rm -rf ${NB_PYTHON_PREFIX}/share/jupyter/lab/staging \ + && find ${CONDA_DIR} -follow -type f -name '*.a' -delete \ + && find ${CONDA_DIR} -follow -type f -name '*.js.map' -delete \ + ; fi + # Revert to default user and home as pwd USER ${NB_USER} WORKDIR ${HOME} diff --git a/apt-extras.txt b/apt-extras.txt index 754a95e..d1d3329 100644 --- a/apt-extras.txt +++ b/apt-extras.txt @@ -12,26 +12,22 @@ manpages-posix-dev curl wget -# Core text editors on a *nix box: vim and emacs +# command line text editors vim emacs-nox emacs-goodies-el - -# A couple of CLI editors that are easier than vim -# micro # currently not working on 18.04 nano -jed -jed-extra + +# GUI text editors +emacs +vim-gtk3 +gedit # powerful terminal-based file manager, better than the one in JLab mc -# for easily managing multiple repositories with one command (perl-doc -# is needed for its help pages to work) -mr -perl-doc - # Regular build tools for compiling common stuff +# most installed with R installation build-essential gfortran @@ -71,11 +67,6 @@ xubuntu-icon-theme tigervnc-standalone-server tigervnc-xorg-extension -# GUI text editors -emacs -vim-gtk3 -gedit - # Git clients and tools git-gui gitg diff --git a/book/_quarto.yml b/book/_quarto.yml index 52cd23d..b4c5d8b 100644 --- a/book/_quarto.yml +++ b/book/_quarto.yml @@ -19,6 +19,7 @@ book: - index.qmd - customizing.qmd - configuration_files.qmd + - r-packages.qmd - desktop.qmd - tex.qmd - jupyter-config.qmd diff --git a/start b/start index 2b0b289..48314f8 100644 --- a/start +++ b/start @@ -46,4 +46,7 @@ for mime_file_path in ${REPO_DIR}/Desktop/*.xml; do done update-mime-database "${MIME_DIR}" +# Run child start in a subshell to contain its environment +[ -f ${REPO_DIR}/childimage/start ] && ( source ${REPO_DIR}/childimage/start ) + exec "$@"