Customize Your Julia Apptainer

Other than using the Apptainer container we provide (.sif), you can customize it on top of that.

To create an Apptainer container you first need to prepare the definition file, and then just use this definition file to generate the SIF container file on the Discovery compute node.

Prepare the definition file

This section will use julia_custom.def as an example.

The full julia_custom.def file can be found at the end of this page, and you can modify it to suit your needs.

To learn more about the Header and Sections of the definition file, check out the Build Recipe.

In order to avoid problems related to Discovery settings, we recommend to use our container as base image.

Our containers typically provide a generic environment on which you can install more of what you need.

You can follow the workflow below.

Find the SIF file provided by the HPC team on Discovery

If you want to use another SIF file provided by Discovery as base image, here is how to find the path:

--- Use module spider learn how to load the SIF file

module spider julia/1.10.0-SIF
----------------------------
  julia: julia/1.10.0-SIF
----------------------------

    You will need to load all module(s) on any one of the lines below before the "julia/1.10.0-SIF" module is available to load.

      custom/2024a

    Help:
      For help contact your site administrators.

--- Load the module

module load custom/2024a
module load julia/1.10.0-SIF

--- Get the path

After it’s loaded, its path is stored in the $SIF variable.

echo $SIF
/fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/julia/1.10.0-SIF/julia.sif

Use SIF file provided by the HPC team on Discovery as base image

With the file path, here is an example of using julia/1.10.0-SIF as base image:

At the very beginning of the definition file, you need to set up the BootStrap and From.

BootStrap: localimage
From: /fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/julia/1.10.0-SIF/julia.sif
  • Bootstrap: This field indicates which bootstrap the Apptainer uses to build the container. In this example, localimage indicates that a local container image is used as the base image.

  • From: Specifies the location of the base image.

Install what you need

You can check out the Build Recipe for more information about different sections in .def file.

The %post section contains the scripts that need to be executed when building the container.

In the %post section, you can use the dnf install -y command to add the additional packages you need.

For example, if you want to install nginx and vim:

%post
dnf install -y nginx vim

It is very important to Not install any global Julia libraries.

They will cause error when you try to install project/home directory libraries.

Build the Container

Reminder

First as a reminder, if you want to build an Apptainer container, please don’t do it on the Login Node.

You should build it on a Compute Node by running an interactive job, or even simpler: using Open OnDemand’s Interactive Shell App.

The second reminder is, you will see the error message if the memory is not enough:

While performing build: while creating squashfs: create command failed: signal: killed:

How to build the container using base image

Go to the location of your definition file, run:

apptainer build --bind="/fs1" julia_custom.sif julia_custom.def
  • --bind="/fs1" is required so that we can use the local repository mirror julia/1.10.0-SIF.

  • julia_custom.sif is the output SIF file. You can name it whatever you like.

  • julia_custom.def is the definition file we just prepared.

Note that --bind="/fs1" is required because the base image we used needs it. If you use other container as base image, it may not be needed.

Now you only need to wait, until you see:

Complete!
INFO:    Creating SIF file...
INFO:    Build complete: julia_custom.sif

You will find julia_custom.sif in the current folder.

Let’s test if nginx was successfully installed.

First we use the apptainer shell command to start an interactive shell session to run commands in the container’s environment.

apptainer shell julia_custom.sif

Apptainer>

Then we can check it by nginx -v command:

Apptainer> nginx -v
nginx version: nginx/1.14.1

Build a Container with New Julia Version Using Rocky Linux Base Image

Use SIF file provided by the HPC team on Discovery as base image to customize your own container is intuitive and convenient, but what if the Julia version you need is not provided?

You can create a definition file from scratch, but since Discovery requires some specific system-level settings, we recommend using the Rocky Linux Base Image to avoid problems related to Discovery settings.

You can find our Rocky Linux base image under /fs1/software/containers/.

An example of creating an julia_1.10.0 Apptainer container using rocky8.sif as base image:

BootStrap: localimage
From: /fs1/software/containers/rocky_8/rocky8.sif
  • Bootstrap: This field indicates which bootstrap the Apptainer uses to build the container. In this example, localimage indicates that a local container image is used as the base image.

  • From: Specifies the location of the base image.

If you would like to install something else, or reduce the installation of something, %post will be the section you want to modify.

The full julia_1.10.0.def file can be found at the end of this page, and you can modify it to suit your needs.

julia_custom.def

BootStrap: localimage
From: /fs1/software/sstack/rhel_8/stacks/custom/2024a/packages/julia/1.10.0-SIF/julia.sif

%post
dnf install -y nginx vim

julia_1.10.0.def

BootStrap: localimage
From: /fs1/software/containers/rocky_8/rocky8.sif
# See '/fs1/software/containers/rocky_8/rocky8.def' for Discovery Cluster specific changes and fixes. '/fs1' will need to be bind mounted during the build.

%runscript
# Run Command
exec "$@"

%environment
export JUPYTER_DATA_DIR="$HOME/.julia/jupyter-sif/1.10"

%post
# Set Mask
umask 0022

# Install Julia + Common Dependencies
dnf install -y -q redhat-lsb-core findutils wget git git-all git-extras ca-certificates gnupg2 pandoc qt5-qtbase-devel "@Development Tools"

# Setup Python 3.9
dnf install -y -q python39 python39-devel python39-pip python39-pyyaml python39-setuptools python39-test python39-toml python39-urllib3 python39-requests python39-cryptography python39-wheel chkconfig
alternatives --set python /usr/bin/python3.9
alternatives --set python3 /usr/bin/python3.9
update-alternatives --install /usr/bin/pip pip /usr/bin/pip3.9 50
update-alternatives --install /usr/bin/pip3 pip3 /usr/bin/pip3.9 50
alternatives --set pip /usr/bin/pip3.9
alternatives --set pip3 /usr/bin/pip3.9

# Install Code Server
#curl -fsSL https://code-server.dev/install.sh | sh -s -- --version=4.11.0
curl -fsSL https://code-server.dev/install.sh | sh -s --

# Install Jupyter Notebook/Lab
python3 -m pip install -q --upgrade pip wheel
python3 -m pip install -q --upgrade notebook jupyterlab jupyterlab-widgets jupyterlab-pygments ipykernel ipywidgets qtconsole pyqt5

# Install Julia
jver_full="1.10.0"
jver_short="1.10"
jpath="/opt/julia/$jver_short"

mkdir -p "$jpath"

curl -fL -o julia.tar.gz "https://julialang-s3.julialang.org/bin/linux/x64/${jver_short}/julia-${jver_full}-linux-x86_64.tar.gz"
tar -xzf julia.tar.gz -C "$jpath" --strip-components 1
/usr/bin/rm -f julia.tar.gz

ln -s "${jpath}/bin/julia" "/usr/local/bin/julia"

# Cleanup dnf Packages
dnf clean all
rm -rf /var/cache/dnf/*

%test
        set -x
        julia --version
        code-server --version
        jupyter-notebook --version
        jupyter-lab --version