diff --git a/all-spark-notebook/Dockerfile b/all-spark-notebook/Dockerfile index 2bffec5f..5f6a7132 100644 --- a/all-spark-notebook/Dockerfile +++ b/all-spark-notebook/Dockerfile @@ -25,13 +25,19 @@ RUN conda install --quiet --yes \ 'r-irkernel=0.7*' \ 'r-ggplot2=2.2*' \ 'r-sparklyr=0.5*' \ - 'r-rcurl=1.95*' && conda clean -tipsy + 'r-rcurl=1.95*' && \ + conda clean -tipsy && \ + fix-permissions $CONDA_DIR # Apache Toree kernel -RUN pip --no-cache-dir install https://dist.apache.org/repos/dist/dev/incubator/toree/0.2.0/snapshots/dev1/toree-pip/toree-0.2.0.dev1.tar.gz -RUN jupyter toree install --sys-prefix +RUN pip install --no-cache-dir \ + https://dist.apache.org/repos/dist/dev/incubator/toree/0.2.0/snapshots/dev1/toree-pip/toree-0.2.0.dev1.tar.gz \ + && \ + jupyter toree install --sys-prefix && \ + fix-permissions $CONDA_DIR # Spylon-kernel RUN conda install --quiet --yes 'spylon-kernel=0.4*' && \ - conda clean -tipsy -RUN python -m spylon_kernel install --sys-prefix + conda clean -tipsy && \ + python -m spylon_kernel install --sys-prefix && \ + fix-permissions $CONDA_DIR diff --git a/base-notebook/Dockerfile b/base-notebook/Dockerfile index e9bda554..70d728bb 100644 --- a/base-notebook/Dockerfile +++ b/base-notebook/Dockerfile @@ -33,25 +33,34 @@ RUN wget --quiet https://github.com/krallin/tini/releases/download/v0.10.0/tini chmod +x /usr/local/bin/tini # Configure environment -ENV CONDA_DIR /opt/conda -ENV PATH $CONDA_DIR/bin:$PATH -ENV SHELL /bin/bash -ENV NB_USER jovyan -ENV NB_UID 1000 -ENV HOME /home/$NB_USER -ENV LC_ALL en_US.UTF-8 -ENV LANG en_US.UTF-8 -ENV LANGUAGE en_US.UTF-8 +ENV CONDA_DIR=/opt/conda \ + SHELL=/bin/bash \ + NB_USER=jovyan \ + NB_UID=1000 \ + NB_OWNER_GROUP=user-writable \ + NB_OWNER_GID=10000 \ + LC_ALL=en_US.UTF-8 \ + LANG=en_US.UTF-8 \ + LANGUAGE=en_US.UTF-8 +ENV PATH=$CONDA_DIR/bin:$PATH \ + HOME=/home/$NB_USER +ADD fix-permissions /usr/local/bin/fix-permissions # Create jovyan user with UID=1000 and in the 'users' group +# and the user-writable group, which owns all of the +# files we want users to write (/home/jovyan, packages) RUN useradd -m -s /bin/bash -N -u $NB_UID $NB_USER && \ mkdir -p $CONDA_DIR && \ - chown $NB_USER $CONDA_DIR + chown $NB_USER $CONDA_DIR && \ + groupadd -g $NB_OWNER_GID $NB_OWNER_GROUP && \ + usermod -G $NB_OWNER_GROUP $NB_USER && \ + fix-permissions /home/$NB_USER USER $NB_USER # Setup work directory for backward-compatibility -RUN mkdir /home/$NB_USER/work +RUN mkdir /home/$NB_USER/work && \ + fix-permissions /home/$NB_USER # Install conda as jovyan and check the md5 sum provided on the download site ENV MINICONDA_VERSION 4.3.21 @@ -65,14 +74,16 @@ RUN cd /tmp && \ $CONDA_DIR/bin/conda config --system --set auto_update_conda false && \ $CONDA_DIR/bin/conda config --system --set show_channel_urls true && \ $CONDA_DIR/bin/conda update --all && \ - conda clean -tipsy + conda clean -tipsy && \ + fix-permissions $CONDA_DIR # Install Jupyter Notebook and Hub RUN conda install --quiet --yes \ 'notebook=5.0.*' \ 'jupyterhub=0.7.*' \ 'jupyterlab=0.27.*' \ - && conda clean -tipsy + && conda clean -tipsy && \ + fix-permissions $CONDA_DIR USER root @@ -88,7 +99,7 @@ COPY start.sh /usr/local/bin/ COPY start-notebook.sh /usr/local/bin/ COPY start-singleuser.sh /usr/local/bin/ COPY jupyter_notebook_config.py /etc/jupyter/ -RUN chown -R $NB_USER:users /etc/jupyter/ +RUN fix-permissions /etc/jupyter/ # Switch back to jovyan to avoid accidental container runs as root USER $NB_USER diff --git a/base-notebook/README.md b/base-notebook/README.md index 11214876..1870cdcd 100644 --- a/base-notebook/README.md +++ b/base-notebook/README.md @@ -58,6 +58,9 @@ You may customize the execution of the Docker container and the command it is ru * `-e NB_GID=100` - Specify the gid of the `jovyan` user. Useful to mount host volumes with specific file ownership. For this option to take effect, you must run the container with `--user root`. (The `start-notebook.sh` script will `su jovyan` after adjusting the group id.) * `-e GRANT_SUDO=yes` - Gives the `jovyan` user passwordless `sudo` capability. Useful for installing OS packages. For this option to take effect, you must run the container with `--user root`. (The `start-notebook.sh` script will `su jovyan` after adding `jovyan` to sudoers.) **You should only enable `sudo` if you trust the user or if the container is running on an isolated host.** * `-v /some/host/folder/for/work:/home/jovyan/work` - Mounts a host machine directory as folder in the container. Useful when you want to preserve notebooks and other work even after the container is destroyed. **You must grant the within-container notebook user or group (`NB_UID` or `NB_GID`) write access to the host directory (e.g., `sudo chown 1000 /some/host/folder/for/work`).** +* `--group-add user-writable` - use this argument if you are also specifying + a specific user id to launch the container (`-u 5000`), rather than launching the container as root and relying on NB_UID and NB_GID to set the user and group. + ## SSL Certificates @@ -111,11 +114,6 @@ conda install some-package ```python # Spawn user containers from this image c.DockerSpawner.container_image = 'jupyter/base-notebook' - -# Have the Spawner override the Docker run command -c.DockerSpawner.extra_create_kwargs.update({ - 'command': '/usr/local/bin/start-singleuser.sh' -}) ``` ### start.sh @@ -137,3 +135,4 @@ This script is particularly useful when you derive a new Dockerfile from this im ### Others You can bypass the provided scripts and specify your an arbitrary start command. If you do, keep in mind that certain features documented above will not function (e.g., `GRANT_SUDO`). + diff --git a/base-notebook/fix-permissions b/base-notebook/fix-permissions new file mode 100755 index 00000000..588e59a2 --- /dev/null +++ b/base-notebook/fix-permissions @@ -0,0 +1,27 @@ +#!/bin/bash +# set permissions on a directory +# after any installation, if a directory needs to be (human) user-writable, +# run this script on it. +# It will make everything in the directory owned by the group $NB_OWNER_GROUP +# and writable by that group. +# Deployments that want to set a specific user id can preserve permissions +# by adding the `--group-add user-writable` line to `docker run`. + +# uses find to avoid touching files that already have the right permissions, +# which would cause massive image explosion + +# right permissions are: +# group=$NB_OWNER_GROUP +# AND permissions include group rwX (directory-execute) + +set -e + +for d in $@; do + find "$d" \ + ! \( \ + -group $NB_OWNER_GROUP \ + -a -perm -g+rwX \ + \) \ + -exec chgrp $NB_OWNER_GROUP {} \; \ + -exec chmod g+rwX {} \; +done diff --git a/base-notebook/start.sh b/base-notebook/start.sh index 099af2b6..c5f957f7 100755 --- a/base-notebook/start.sh +++ b/base-notebook/start.sh @@ -13,14 +13,6 @@ if [ $(id -u) == 0 ] ; then if [ "$NB_UID" != $(id -u $NB_USER) ] ; then echo "Set user UID to: $NB_UID" usermod -u $NB_UID $NB_USER - # Careful: $HOME might resolve to /root depending on how the - # container is started. Use the $NB_USER home path explicitly. - for d in "$CONDA_DIR" "$JULIA_PKGDIR" "/home/$NB_USER"; do - if [[ ! -z "$d" && -d "$d" ]]; then - echo "Set ownership to uid $NB_UID: $d" - chown -R $NB_UID "$d" - fi - done fi # Change GID of NB_USER to NB_GID if NB_GID is passed as a parameter diff --git a/datascience-notebook/Dockerfile b/datascience-notebook/Dockerfile index 7f98a99a..a3e5a06e 100644 --- a/datascience-notebook/Dockerfile +++ b/datascience-notebook/Dockerfile @@ -30,7 +30,8 @@ RUN . /etc/os-release && \ echo "push!(Libdl.DL_LOAD_PATH, \"$CONDA_DIR/lib\")" >> /usr/etc/julia/juliarc.jl && \ # Create JULIA_PKGDIR \ mkdir $JULIA_PKGDIR && \ - chown -R $NB_USER:users $JULIA_PKGDIR + chown $NB_USER $JULIA_PKGDIR && \ + fix-permissions $JULIA_PKGDIR USER $NB_USER @@ -52,7 +53,9 @@ RUN conda config --system --add channels r && \ 'r-caret=6.0*' \ 'r-rcurl=1.95*' \ 'r-crayon=1.3*' \ - 'r-randomforest=4.6*' && conda clean -tipsy + 'r-randomforest=4.6*' && \ + conda clean -tipsy && \ + fix-permissions $CONDA_DIR # Add Julia packages # Install IJulia as jovyan and then move the kernelspec out @@ -72,5 +75,6 @@ RUN julia -e 'Pkg.init()' && \ # move kernelspec out of home \ mv $HOME/.local/share/jupyter/kernels/julia* $CONDA_DIR/share/jupyter/kernels/ && \ chmod -R go+rx $CONDA_DIR/share/jupyter && \ - rm -rf $HOME/.local + rm -rf $HOME/.local && \ + fix-permissions $JULIA_PKGDIR $CONDA_DIR/share/jupyter diff --git a/r-notebook/Dockerfile b/r-notebook/Dockerfile index c9559d54..ed117684 100644 --- a/r-notebook/Dockerfile +++ b/r-notebook/Dockerfile @@ -32,4 +32,6 @@ RUN conda install --quiet --yes \ 'r-caret=6.0*' \ 'r-rcurl=1.95*' \ 'r-crayon=1.3*' \ - 'r-randomforest=4.6*' && conda clean -tipsy + 'r-randomforest=4.6*' && \ + conda clean -tipsy && \ + fix-permissions $CONDA_DIR diff --git a/scipy-notebook/Dockerfile b/scipy-notebook/Dockerfile index 8f528eef..130d624e 100644 --- a/scipy-notebook/Dockerfile +++ b/scipy-notebook/Dockerfile @@ -42,13 +42,14 @@ RUN conda install --quiet --yes \ 'beautifulsoup4=4.5.*' \ 'xlrd' && \ conda remove --quiet --yes --force qt pyqt && \ - conda clean -tipsy - -# Activate ipywidgets extension in the environment that runs the notebook server -RUN jupyter nbextension enable --py widgetsnbextension --sys-prefix + conda clean -tipsy && \ + # Activate ipywidgets extension in the environment that runs the notebook server + jupyter nbextension enable --py widgetsnbextension --sys-prefix && \ + fix-permissions $CONDA_DIR # Import matplotlib the first time to build the font cache. ENV XDG_CACHE_HOME /home/$NB_USER/.cache/ -RUN MPLBACKEND=Agg python -c "import matplotlib.pyplot" +RUN MPLBACKEND=Agg python -c "import matplotlib.pyplot" && \ + fix-permissions /home/$NB_USER USER $NB_USER diff --git a/tensorflow-notebook/Dockerfile b/tensorflow-notebook/Dockerfile index 15808556..24b3d24f 100644 --- a/tensorflow-notebook/Dockerfile +++ b/tensorflow-notebook/Dockerfile @@ -4,5 +4,7 @@ FROM jupyter/scipy-notebook MAINTAINER Jupyter Project -# Install Python 3 Tensorflow -RUN conda install --quiet --yes 'tensorflow=1.0*' +# Install Tensorflow +RUN conda install --quiet --yes 'tensorflow=1.0*' && \ + conda clean -tipsy && \ + fix-permissions $CONDA_DIR