apptainer(1)

okay so you opened the apptainer(1) manual and landed on the build page β€” welcome, bestie, this is the one where we make a container image out of basically anything. πŸ’–

🌸 NAME 🌸

apptainer-build β€” build an Apptainer image ✨

πŸ¦‹ SYNOPSIS πŸ¦‹

apptainer build [local options...]

πŸŽ€ DESCRIPTION πŸŽ€

πŸ’… IMAGE PATH (aka what comes out the other side)

When Apptainer builds the container, the output can be one of a few formats, and this is literally the whole personality of your build:

  • default: the compressed Apptainer read only image format β€” this is the default
  • sandbox: a read-write container living inside a directory structure
note: it is a common workflow to use the sandbox mode for development of the container, and then build it as a default Apptainer image for production use. The default format is immutable β€” no cap, you cannot poke at it afterwards.

🌈 BUILD SPEC (aka what goes in)

The build spec target is a definition (def) file, local image, or URI that can be used to create an Apptainer container. Several different local target formats exist, and they are all valid:

  • def file : this is a recipe for building a container (examples below πŸ“)
  • buildkit: a build context directory, containing a Dockerfile to build
  • directory: a directory structure containing a (ch)root file system
  • image: a local image on your machine (will convert to sif if it is legacy format)

Targets can also be remote and defined by a URI of the following formats:

  • library:// β€” an image library (no default)
  • docker:// β€” a Docker/OCI registry (default Docker Hub)
  • shub:// β€” an Apptainer registry (default Singularity Hub)
  • oras:// β€” an OCI registry that holds SIF files using ORAS
  • ipfs:// β€” an IPFS cluster, using a HTTP gateway

🧚 Temporary files (the space situation)

The location used for temporary directories defaults to /tmp but can be overridden by the TMPDIR environment variable, and that can be overridden by the APPTAINER_TMPDIR environment variable. The temporary directory used during a build must be on a filesystem that has enough space to hold the entire container image, uncompressed, including any temporary files that are created and later removed during the build. You may need to set APPTAINER_TMPDIR or TMPDIR when building a large container on a system that has a small /tmp filesystem.

fr fr read this one β€” if your /tmp is tiny your big build is gonna have a bad time 😭

✨ OPTIONS ✨

  • --arch="amd64" β€” architecture to build for
  • --arch-variant="" β€” architecture variant to build for
  • --authfile="" β€” Docker-style authentication file to use for writing/reading OCI registry credentials
  • -B, --bind=[] β€” a user-bind path specification. spec has the format src[:dest[:opts]], where src and dest are outside and inside paths. If dest is not given, it is set equal to src. Mount options ('opts') may be specified as 'ro' (read-only) or 'rw' (read/write, which is the default). Multiple bind paths can be given by a comma separated list.
  • --build-arg=[] β€” defines variable=value to replace {{ variable }} entries in build definition file
  • --build-arg-file="" β€” specifies a file containing variable=value lines to replace '{{ variable }}' with value in build definition files
  • --buildkit-host="" β€” specify a custom BuildKit daemon host
  • --data[=false] β€” build image with data partition instead of system partition
  • --disable-cache[=false] β€” do not use cache or create cache
  • --docker-host="" β€” specify a custom Docker daemon host
  • --docker-login[=false] β€” login to a Docker Repository interactively
  • -e, --encrypt[=false] β€” build an image with an encrypted file system πŸ”
  • -f, --fakeroot[=false] β€” build with the appearance of running as root (default when building from a definition file unprivileged)
  • --fix-perms[=false] β€” ensure owner has rwX permissions on all container content for oci/docker sources
  • -F, --force[=false] β€” overwrite an image file if it exists
  • -h, --help[=false] β€” help for build
  • --json[=false] β€” interpret build definition as JSON
  • --library="" β€” container Library URL
  • --mksquashfs-args="" β€” extra arguments to pass to mksquashfs when creating SIF files
  • --mount=[] β€” a mount specification e.g. 'type=bind,src=/opt,dst=/hostopt'.
  • --no-cleanup[=false] β€” do NOT clean up bundle after failed build, can be helpful for debugging
  • --no-https[=false] β€” use http instead of https for docker:// oras:// and library:///... URIs
  • -T, --notest[=false] β€” build without running tests in %test section
  • --nv[=false] β€” inject host Nvidia libraries during build for post and test sections
  • --nvccli[=false] β€” use nvidia-container-cli for GPU setup (experimental)
  • --passphrase[=false] β€” prompt for an encryption passphrase
  • --pem-path="" β€” enter an path to a PEM formatted RSA key for an encrypted container
  • --reproducible[=false] β€” creates a reproducible build by using the creation date of the source image
  • --rocm[=false] β€” inject host Rocm libraries during build for post and test sections
  • -s, --sandbox[=false] β€” build image as sandbox format (chroot directory structure)
  • --section=[all] β€” only run specific section(s) of deffile (setup, post, files, environment, test, labels, none)
  • -u, --update[=false] β€” run definition over existing container (skips header)
  • --userns[=false] β€” build without using setuid even if available
  • --warn-unused-build-args[=false] β€” shows warning instead of fatal message when build args are not exact matched
  • --writable-tmpfs[=false] β€” during the %test section, makes the file system accessible as read-write with non persistent data (with overlay support only)

🌟 EXAMPLE 🌟

πŸ“ DEF FILE BASE OS

Library:
    Bootstrap: library
    From: debian:9

Docker:
    Bootstrap: docker
    From: tensorflow/tensorflow:latest
    IncludeCmd: yes # Use the CMD as runscript instead of ENTRYPOINT

Singularity Hub:
    Bootstrap: shub
    From: singularityhub/centos

YUM/RHEL:
    Bootstrap: yum
    OSVersion: 7
    MirrorURL: http://mirror.centos.org/centos-%{OSVERSION}/%{OSVERSION}/os/x86_64/
    Include: yum

SUSE:
    Bootstrap: zypper # on SLE system registration of build host is used
    Include: zypper

openSUSE:
    Bootstrap: zypper
    MirrorURL: http://download.opensuse.org/distribution/openSUSE-stable/repo/oss
    Include: zypper

Debian/Ubuntu:
    Bootstrap: debootstrap
    OSVersion: trusty
    MirrorURL: http://us.archive.ubuntu.com/ubuntu/

Local Image:
    Bootstrap: localimage
    From: /home/dave/starter.img

Scratch:
    Bootstrap: scratch # Populate the container with a minimal rootfs in %setup

πŸ¦‹ DEFFILE SECTIONS

The following sections are presented in the order of processing, with the exception that labels and environment can also be manipulated in %post.

%pre
    echo "This is a scriptlet that will be executed on the host, as root before"
    echo "the container has been bootstrapped. This section is not commonly used."

%setup
    echo "This is a scriptlet that will be executed on the host, as root, after"
    echo "the container has been bootstrapped. To install things into the container"
    echo "reference the file system location with $APPTAINER_ROOTFS."

%files
    /path/on/host/file.txt /path/on/container/file.txt
    relative_file.txt /path/on/container/relative_file.txt

%post
    echo "This scriptlet section will be executed from within the container after"
    echo "the bootstrap/base has been created and setup."

%environment
    LUKE=goodguy
    VADER=badguy
    HAN=someguy
    export HAN VADER LUKE

%test
    echo "Define any test commands that should be executed after container has been"
    echo "built. This scriptlet will be executed from within the running container"
    echo "as the root user. Pay attention to the exit/return value of this scriptlet"
    echo "as any non-zero exit code will be assumed as failure."
    exit 0

%runscript
    echo "Define actions for the container to be executed with the run command or"
    echo "when container is executed."

%startscript
    echo "Define actions for container to perform when started as an instance."

%labels
    HELLO MOTO
    KEY VALUE

%help
    This is a text file to be displayed with the run-help command.

🌈 COMMANDS

Build a sif file from an Apptainer recipe file:

$ apptainer build /tmp/debian0.sif /path/to/debian.def

Build a sif image from the Library:

$ apptainer build /tmp/debian1.sif library://debian:latest

Build a base sandbox from DockerHub, make changes to it, then build sif β€” this is the iconic dev-to-prod glow-up right here, obsessed πŸ‘‘

$ apptainer build --sandbox /tmp/debian docker://debian:latest
$ apptainer exec --writable /tmp/debian apt-get install python
$ apptainer build /tmp/debian2.sif /tmp/debian

🫢 SEE ALSO 🫢

πŸ’œ HISTORY πŸ’œ

22-Oct-2026 Auto generated by spf13/cobra


and that's the page, bestie β€” you're literally a container builder now πŸ’…βœ¨ This whole thing is from the apptainer(1) manual, auto generated by spf13/cobra and dated Oct 2026, back on the apptainer(1) tip. Go build something cute πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from
  • epel 9: apptainer 1.5.5-1.el9 Β· Apache-2.0 AND BSD-2-Clause AND BSD-3-Clause AND BSD-3-Clause-LBNL AND ISC AND MIT AND MPL-2.0 AND Unlicense
  • πŸ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms