install notebook in its own env
leave the conda root env alone
adds conda activation to profile.d and ensures that we
start with a login shell via the ENTRYPOINT
MODIFY
repo2docker/buildpacks/base.py
repo2docker/buildpacks/base.py
@@ -156,6 +156,9 @@ RUN ./{{ s }}
{% if start_script is not none -%}
RUN chmod +x "{{ start_script }}"
ENTRYPOINT ["{{ start_script }}"]
+{% else %}
+COPY /repo2docker-entrypoint /usr/local/bin/repo2docker-entrypoint
+ENTRYPOINT ["/usr/local/bin/repo2docker-entrypoint"]
{% endif -%}
# Specify the default command to run
@@ -167,6 +170,11 @@ CMD ["jupyter", "notebook", "--ip", "0.0.0.0"]
{% endif %}
"""
+ENTRYPOINT_FILE = os.path.join(
+ os.path.dirname(os.path.abspath(__file__)),
+ "repo2docker-entrypoint",
+)
+
class BuildPack:
"""
@@ -493,6 +501,8 @@ class BuildPack:
src_path = os.path.join(os.path.dirname(__file__), *src_parts)
tar.add(src_path, src, filter=_filter_tar)
+ tar.add(ENTRYPOINT_FILE, "repo2docker-entrypoint", filter=_filter_tar)
+
tar.add('.', 'src/', filter=_filter_tar)
tar.close()

MODIFY
repo2docker/buildpacks/conda/__init__.py
repo2docker/buildpacks/conda/__init__.py
@@ -28,7 +28,7 @@ class CondaBuildPack(BaseImage):
"""
env = super().get_build_env() + [
('CONDA_DIR', '${APP_BASE}/conda'),
- ('NB_PYTHON_PREFIX', '${CONDA_DIR}'),
+ ('NB_PYTHON_PREFIX', '${CONDA_DIR}/envs/notebook'),
]
if self.py2:
env.append(('KERNEL_PYTHON_PREFIX', '${CONDA_DIR}/envs/kernel'))
@@ -42,9 +42,10 @@ class CondaBuildPack(BaseImage):
"""
path = super().get_path()
+ path.insert(0, '${CONDA_DIR}/bin')
if self.py2:
path.insert(0, '${KERNEL_PYTHON_PREFIX}/bin')
- path.insert(0, '${CONDA_DIR}/bin')
+ path.insert(0, '${NB_PYTHON_PREFIX}/bin')
return path
def get_build_scripts(self):
@@ -97,6 +98,7 @@ class CondaBuildPack(BaseImage):
"""
files = {
'conda/install-miniconda.bash': '/tmp/install-miniconda.bash',
+ 'conda/activate-conda.sh': '/etc/profile.d/activate-conda.sh',
}
py_version = self.python_version
self.log.info("Building conda environment for python=%s" % py_version)
@@ -174,16 +176,16 @@ class CondaBuildPack(BaseImage):
"""
assembly_scripts = []
environment_yml = self.binder_path('environment.yml')
- env_name = 'kernel' if self.py2 else 'root'
+ env_prefix = "${KERNEL_PYTHON_PREFIX}" if self.py2 else "${NB_PYTHON_PREFIX}"
if os.path.exists(environment_yml):
assembly_scripts.append((
'${NB_USER}',
r"""
- conda env update -n {0} -f "{1}" && \
+ conda env update -p {0} -f "{1}" && \
conda clean -tipsy && \
conda list -n {0} && \
rm -rf /srv/conda/pkgs
- """.format(env_name, environment_yml)
+ """.format(env_prefix, environment_yml)
))
return super().get_assemble_scripts() + assembly_scripts

ADD
repo2docker/buildpacks/conda/activate-conda.sh
+# enable conda and activate the notebook environment
+CONDA_PROFILE="${CONDA_DIR}/etc/profile.d/conda.sh"
+test -f $CONDA_PROFILE && . $CONDA_PROFILE
+if [[ "${KERNEL_PYTHON_PREFIX}" != "${NB_PYTHON_PREFIX}" ]]; then
+ # if the kernel is a separate env, stack them
+ # so both are on PATH
+ conda activate ${KERNEL_PYTHON_PREFIX}
+ conda activate --stack ${NB_PYTHON_PREFIX}
+else
+ conda activate ${NB_PYTHON_PREFIX}
+fi

MODIFY
repo2docker/buildpacks/conda/install-miniconda.bash
repo2docker/buildpacks/conda/install-miniconda.bash
@@ -34,22 +34,21 @@ conda config --system --add channels conda-forge
conda config --system --set auto_update_conda false
conda config --system --set show_channel_urls true
-# install conda itself
-conda install -yq conda==${CONDA_VERSION}
-
-# switch Python in its own step
-# since switching Python during an env update can
-# prevent pip installation.
-# we wouldn't have this issue if we did `conda env create`
-# instead of `conda env update` in these cases
-conda install -y $(cat /tmp/environment.yml | grep -o '\spython=.*') conda==${CONDA_VERSION}
-
# bug in conda 4.3.>15 prevents --set update_dependencies
echo 'update_dependencies: false' >> ${CONDA_DIR}/.condarc
-echo "installing root env:"
+# install conda itself
+conda install -yq conda==${CONDA_VERSION}
+
+echo "installing notebook env:"
cat /tmp/environment.yml
-conda env update -n root -f /tmp/environment.yml
+conda env create -p ${NB_PYTHON_PREFIX} -f /tmp/environment.yml
+
+# empty conda history file,
+# which seems to result in some effective pinning of packages in the initial env,
+# which we don't intend.
+# this file must not be *removed*, however
+echo '' > ${NB_PYTHON_PREFIX}/conda-meta/history
# enable nteract-on-jupyter, which was installed with pip
jupyter serverextension enable nteract_on_jupyter --sys-prefix
@@ -59,15 +58,11 @@ if [[ -f /tmp/kernel-environment.yml ]]; then
echo "installing kernel env:"
cat /tmp/kernel-environment.yml
- conda env create -n kernel -f /tmp/kernel-environment.yml
- ${CONDA_DIR}/envs/kernel/bin/ipython kernel install --prefix "${CONDA_DIR}"
- echo '' > ${CONDA_DIR}/envs/kernel/conda-meta/history
+ conda env create -p ${KERNEL_PYTHON_PREFIX} -f /tmp/kernel-environment.yml
+ ${KERNEL_PYTHON_PREFIX}/bin/ipython kernel install --prefix "${CONDA_DIR}"
+ echo '' > ${KERNEL_PYTHON_PREFIX}/envs/kernel/conda-meta/history
+ conda list -p ${KERNEL_PYTHON_PREFIX}
fi
-# empty conda history file,
-# which seems to result in some effective pinning of packages in the initial env,
-# which we don't intend.
-# this file must not be *removed*, however
-echo '' > ${CONDA_DIR}/conda-meta/history
# Clean things out!
conda clean -tipsy
@@ -77,4 +72,5 @@ rm ${INSTALLER_PATH}
chown -R $NB_USER:$NB_USER ${CONDA_DIR}
-conda list
+conda list -n root
+conda list -p ${NB_PYTHON_PREFIX}

ADD
repo2docker/buildpacks/repo2docker-entrypoint
+#!/bin/bash -l
+# lightest possible entrypoint that ensures that
+# we use a login shell to get a fully configured shell environment
+# (e.g. sourcing /etc/profile.d, ~/.bashrc, and friends)
+exec "$@"

install notebook in its own env

leave the conda root env alone

adds conda activation to profile.d and ensures that we
start with a login shell via the ENTRYPOINT