diff --git a/docs/source/config_files.rst b/docs/source/config_files.rst index 3144088b..5133c594 100644 --- a/docs/source/config_files.rst +++ b/docs/source/config_files.rst @@ -121,6 +121,20 @@ An example usecase of ``postBuild`` file is JupyterLab's demo on mybinder.org. It uses a ``postBuild`` file in a folder called ``binder`` to `prepare their demo for binder `_. +.. _start: + +``start`` +^^^^^^^^^ + +A script that can contain arbitrary commands to be run at runtime (as an +`ENTRYPOINT ` +to the docker container). If you want this to be a shell script, make sure the +first line is ```#!/bin/bash``. The last line must be ```exec "$@"``` +equivalent. + +.. TODO: Discuss runtime limits, best practices, etc. + Also, point to an example. + .. _runtime.txt: ``runtime.txt`` diff --git a/docs/source/dev_newbuildpack.md b/docs/source/dev_newbuildpack.md index 05ac93bf..fd6dd7c6 100644 --- a/docs/source/dev_newbuildpack.md +++ b/docs/source/dev_newbuildpack.md @@ -23,4 +23,4 @@ Note that this doesn't apply to adding additional libraries / UI to existing buildpacks. For example, if we had an R buildpack and it supported IRKernel, it is much easier to just support RStudio / Shiny with it, since those are library additions than entirely -new buildpacks. \ No newline at end of file +new buildpacks. diff --git a/repo2docker/buildpacks/base.py b/repo2docker/buildpacks/base.py index 4df7686a..545f3d85 100644 --- a/repo2docker/buildpacks/base.py +++ b/repo2docker/buildpacks/base.py @@ -131,6 +131,12 @@ RUN ./{{ s }} {% endfor %} {% endif -%} +# Add start script +{% if start_script -%} +RUN chmod +x "{{ start_script }}" +ENTRYPOINT ["{{ start_script }}"] +{% endif -%} + # Specify the default command to run CMD ["jupyter", "notebook", "--ip", "0.0.0.0"] @@ -333,6 +339,21 @@ class BuildPack: """ return [] + def get_start_script(self): + """ + An ordered list of executable scripts to be executated at runtime. + These scripts are added as an `ENTRYPOINT` to the container. + + Is run as a non-root user, and must be executable. Used for doing + things that are currently not supported by other means and need to be + applied at runtime (set environment variables). + + The scripts should be as deterministic as possible - running it twice + should not produce different results. + + """ + return '' + def binder_path(self, path): """Locate a file""" if os.path.exists('binder'): @@ -380,6 +401,7 @@ class BuildPack: build_script_files=self.get_build_script_files(), base_packages=sorted(self.get_base_packages()), post_build_scripts=self.get_post_build_scripts(), + start_script=self.get_start_script(), appendix=self.appendix, ) @@ -519,3 +541,9 @@ class BaseImage(BuildPack): if os.path.exists(post_build): return [post_build] return [] + + def get_start_script(self): + start = self.binder_path('start') + if os.path.exists(start): + return start + return '' diff --git a/tests/venv/start/postBuild/README.rst b/tests/venv/start/postBuild/README.rst new file mode 100644 index 00000000..1a9851f3 --- /dev/null +++ b/tests/venv/start/postBuild/README.rst @@ -0,0 +1,8 @@ +System - Post-build scripts +--------------------------- + +It is possible to run scripts after you've built the environment specified in +your other files. This could be used to, for example, download data or run +some configuration scripts. + +In this example, we download and install a Jupyter Notebook extension. diff --git a/tests/venv/start/postBuild/postBuild b/tests/venv/start/postBuild/postBuild new file mode 100755 index 00000000..28b840f0 --- /dev/null +++ b/tests/venv/start/postBuild/postBuild @@ -0,0 +1,2 @@ +#!/bin/bash +jupyter nbextension enable --py --sys-prefix ipyleaflet diff --git a/tests/venv/start/postBuild/requirements.txt b/tests/venv/start/postBuild/requirements.txt new file mode 100644 index 00000000..5a2f5096 --- /dev/null +++ b/tests/venv/start/postBuild/requirements.txt @@ -0,0 +1 @@ +ipyleaflet diff --git a/tests/venv/start/postBuild/start b/tests/venv/start/postBuild/start new file mode 100644 index 00000000..c458c91a --- /dev/null +++ b/tests/venv/start/postBuild/start @@ -0,0 +1,5 @@ +#!/bin/bash + +export TEST_START_VAR="var is set" + +exec "$@" diff --git a/tests/venv/start/postBuild/verify b/tests/venv/start/postBuild/verify new file mode 100755 index 00000000..cc0d9ea7 --- /dev/null +++ b/tests/venv/start/postBuild/verify @@ -0,0 +1,9 @@ +#!/bin/bash +set -euo pipefail +jupyter nbextension list | grep 'jupyter-leaflet' | grep enabled + +if [ "$TEST_START_VAR" != "var is set" ] +then + echo "TEST_START_VAR is not set" + exit 1 +fi