Adding customizations to images
After you download the image for the runtime that you want to customize, you can build a new custom image by adding your software customizations to the downloaded image.
Customizing images
- Operating system dependencies
- Python packages for user code
- JupyterLab extensions
General steps for creating custom images
- In an empty directory, create the following
Dockerfile:ARG base_image_tag=custom_image_base:latest FROM ${base_image_tag} # ============ # root section # ============ USER root:root COPY install-as-root.sh /tmp/install/ RUN umask 022 \ && for env in /etc/profile.d/env-*.sh ; do source $env ; done \ && bash /tmp/install/install-as-root.sh \ && /opt/ibm/build/bin/microdnf-clean.sh \ && source $DSX_JUPYTER_VENV/bin/activate pip cache purge \ && rm -rf /tmp/install # The microdnf-clean.sh script also grants required permissions. # ----------------------------------------- # Change display name of the Jupyter kernel # ----------------------------------------- # Changing the display name of the kernel allows for distinguishing different # custom images from the default runtime images when editing a notebook. # It is good practice, but not strictly required. RUN sed -i -e '/display_name/{s/",/ with modifications",/}' \ /opt/ibm/run/kernels/*/kernel.json # ============ # user section # ============ USER wsbuild:wsbuild COPY --chown=wsbuild install-as-user.sh /tmp/install/ RUN umask 002 \ && for env in /etc/profile.d/env-*.sh ; do source $env ; done \ && bash /tmp/install/install-as-user.sh \ && source $DSX_KERNEL_VENV/bin/activate pip cache purge \ && rm -rf /tmp/install # ======== # finalize # ======== USER nobody:wsbuild - Edit the
Dockerfilescript:- In the
FROMline at the top, replace${base_image_tag}with the:tagof the runtime image on which you base your customization. - If you add files to the custom image, put
COPYstatements into the root section or user section of the Dockerfile. Files and directories that should be writeable for users must be owned by groupwsbuild(gid 3000) and have group write permission. - Optionally, in the
RUN sedline, edit the comment to include information for notebook editors that tells them which custom image they are using.
- In the
- Create the following
install-as-root.shscript:#!/bin/bash set -e -o pipefail # ============================================================================= # Commands in this script will be executed as root. Use this to... # - install operating system packages # - modify the installed JupyterLab and Notebook servers # ============================================================================= # ----------------------------------------------------------------------------- # The IBM runtime images are based on Red Hat UBI minimal. # The package manager is microdnf, it uses yum repositories. # update all operating system packages microdnf update -y # add microdnf commands to install RPMs here # ----------------------------------------------------------------------------- # The Jupyter virtual environment is where JupyterLab and Notebook run from. source $DSX_JUPYTER_VENV/bin/activate # add pip commands to install lab extensions here - Add commands at the end of
install-as-root.shif you want to install operating system packages or to perform other modifications that require root permission. For example, to install the packagepoppler-utilsand its dependencies from the RedHat UBI repositories, add:microdnf install -y --nodocs poppler-utils - Finally, create the
install-as-user.shscript:#!/bin/bash set -e -o pipefail # ----------------------------------------------------------------------------- # The kernel virtual environment is where user code runs. source $DSX_KERNEL_VENV/bin/activate # add pip commands to install packages for user code here - Edit
install-as-user.shand add commands at the end of script if you want to install Python packages into the virtual environment where user code will be executed. For example, to install the packageseawaterfrom PyPI, add:pip install seawater
If you install multiple packages, call pip install only once, with the full list
of package specifications. This way you ensure that pip selects dependencies that
are compatible with all of the packages that you are adding.
Examples of customizations
The following examples show different ways in which runtimes can be customized. In addition to
the installation of libraries through pip, you can also install JupyterLab
extensions.
- Installing packages for user code
- The following code snippet shows how to install two packages that will be available to user code
in a Python notebook. The code snippet must be added to the end of the
install-as-user.shscript, after this comment:# add pip commands to install packages for user code here pip install astropy==7.2.0 "biopython<2"This code will install the specified version of
astropy, and the latest 1.x version ofbiopython. Missing dependencies for these packages will also be installed, picking the latest suitable version for each dependency.Note: The<and>characters have special meaning in shell scripts. Package specifications that use these characters, likebiopythonin the example, must be enclosed within double quotes (") or single quotes ('). - Installing JupyterLab extensions
-
The following code snippet shows how to install two JupyterLab extensions, which are automatically enabled for both JupyterLab and standalone notebooks. The code snippet must be added to the end of the
install-as-root.shscript, after this comment:# add pip commands to install lab extensions here pip install jupyterlab_freeze jupyterlab_execute_time