Skip to content

3. Using containers to run commands

Overview

Questions

  • How do I use container software on the cluster?
  • How do I run different commands within a container?
  • How do I access an interactive shell within a container?

Objectives

  • Learn how to run different commands when starting a container.
  • Learn how to open an interactive shell within a container environment.

Pulling a new image and running a container

Lets continue by pulling a new image from another public image repository and start to work with the container.

code

$ apptainer pull docker://ghcr.io/apptainer/lolcow
INFO:    Converting OCI blobs to SIF format
INFO:    Starting build...
Getting image source signatures
Copying blob 5ca731fc36c2 done
Copying blob 16ec32c2132b done
Copying config fd0daa4d89 done
Writing manifest to image destination
Storing signatures
2023/02/09 12:20:21  info unpack layer: sha256:16ec32c2132b43494832a05f2b02f7a822479f8250c173d0ab27b3de78b2f058
2023/02/09 12:20:24  info unpack layer: sha256:5ca731fc36c28789c5ddc3216563e8bfca2ab3ea10347e07554ebba1c953242e
INFO:    Creating SIF file...

We pulled a Docker image from a Docker image repo using theapptainer pull command and directed it to store the image file using the default name lolcow_latest.sif in the current directory. If you run the ls command, you should see that the lolcow_latest.sif file is now present in the current directory. This is our image and we can now run a container based on this image:

"code

$ apptainer run lolcow_latest.sif 
 _______________________________
< Thu Apr 25 13:05:47 NZST 2024 >
 -------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
  • Most images are also directly executable
$ ./lolcow_latest.sif

How did the container determine what to do when we ran it?! What did running the container actually do to result in the displayed output?

When you run a container from a sif image without using any additional command line arguments, the container runs the default run script that is embedded within the image. This is a shell script that can be used to run commands, tools or applications stored within the image on container startup. We can inspect the image’s run script using the apptainer inspect command:

code

$ apptainer inspect -r lolcow_latest.sif | head
#!/bin/sh
OCI_ENTRYPOINT='"/bin/sh" "-c" "date | cowsay | lolcat"'
OCI_CMD=''

# When SINGULARITY_NO_EVAL set, use OCI compatible behavior that does
# not evaluate resolved CMD / ENTRYPOINT / ARGS through the shell, and
# does not modify expected quoting behavior of args.
if [ -n "$SINGULARITY_NO_EVAL" ]; then
    # ENTRYPOINT only - run entrypoint plus args
    if [ -z "$OCI_CMD" ] && [ -n "$OCI_ENTRYPOINT" ]; then

This shows us the first 10 lines of the script within the lolcow_latest.sif image configured to run by default when we use the apptainer run command.

Running specific commands within a container

We saw earlier that we can use the apptainer inspect command to see the run script that a container is configured to run by default. What if we want to run a different command within a container?

If we know the path of an executable that we want to run within a container, we can use the apptainer exec command. For example, using the lolcow_latest.sif container that we’ve already pulled from DockerHub, we can run the following within the test directory where the lolcow_latest.sif file is located:

code

$ apptainer exec lolcow_latest.sif echo Hello World!
Hello World!

Here we see that a container has been started from the lolcow_latest.sif image and the echo command has been run within the container, passing the input Hello World!. The command has echoed the provided input to the console and the container has terminated.

Note that the use of apptainer exec has overriden any run script set within the image metadata and the command that we specified as an argument to apptainer exec has been run instead.

Running a different command within the “lolcow” container

Can you run a command to "print date and time" on the container image lolcow_latest.sif

Answer
$ apptainer exec lolcow_latest.sif date

The difference between apptainer run and apptainer exec

Above we used the apptainer exec command. In earlier examples we used apptainer run. To clarify, the difference between these two commands is:

  • apptainer run: This will run the default command set for containers based on the specfied image. This default command is set within the image metadata when the image is built (we’ll see more about this in later episodes). You do not specify a command to run when using apptainer run, you simply specify the image file name. As we saw earlier, you can use the apptainer inspect command to see what command is run by default when starting a new container based on an image.

  • apptainer exec: This will start a container based on the specified image and run the command provided on the command line following apptainer exec <image file name>. This will override any default command specified within the image metadata that would otherwise be run if you used apptainer run.

Opening an interactive shell within a container

If you want to open an interactive shell within a container, Singularity provides the apptainer shell command. Again, using the lolcow_latest.sif image, and within our test directory, we can run a shell within a container from the hello-world image:

code

$ apptainer shell lolcow_latest.sif
Apptainer> whoami
Apptainer> pwd

  • As shown above, we have opened a shell in a new container started from the lolcow_latest.sif image. Note that the shell prompt has changed to show we are now within the container.

Use the exit command to exit from the container shell.

Key Points

  • The apptainer exec is an alternative to apptainer run that allows you to start a container running a specific command.

  • The apptainer shell command can be used to start a container and run an interactive shell within it.