# README
internal/pkg/runtime/launcher/oci
This package contains routines that configure and launch a container in an OCI
bundle format, using a low-level OCI runtime, either crun
or runc
at this
time. crun
is currently preferred. runc
is used where crun
is not
available.
Note - at present, all functionality works with either crun
or runc
.
However, in future crun
may be required for all functionality, as runc
does
not support some limited ID mappings etc. that may be beneficial in an HPC
scenario.
The package contrasts with internal/pkg/runtime/launcher/native
which executes
Singularity format containers (SIF/Sandbox/squashfs/ext3), using one of our own
runtime engines (internal/pkg/runtime/engine/*
).
There are two flows that are implemented here.
- Basic OCI runtime operations against an existing bundle, which will be executed
via the
singularity oci
command group. These are not widely used by end-users of singularity. - A
Launcher
, that implements anExec
function that will be called by 'actions' (run/shell/exec) in--oci
mode, and will:- Prepare an OCI bundle according to
launcher.Options
passed through from the CLI layer. - Execute the bundle, interactively, via the OCI Run operation.
- Prepare an OCI bundle according to
Note - this area of code is under heavy development for experimental introduction in CE 3.11. It is likely that it will be heavily refactored, and split, in future.
Basic OCI Operations
The following files implement basic OCI operations on a runtime bundle:
oci_linux.go
Defines constants, path resolution, and minimal bundle locking functions.
oci_runc_linux.go
Holds implementations of the Run / Start / Exec / Kill / Delete / Pause / Resume / State OCI runtime operations.
See https://github.com/opencontainers/runtime-spec/blob/main/runtime.md#operations
These functions are thin wrappers around the runc
/crun
operations of the
same name.
oci_conmon_linux.go
Hold an implementation of the Create OCI runtime operation. This calls out to
conmon
, which in turn calls crun
or runc
.
conmon
is used to manage logging and console streams for containers that are
started backgrounded, so we don't have to do that ourselves.
oci_attach_linux.go
Implements an Attach
function, which can attach the user's console to the
streams of a container running in the background, which is being monitored by
conmon.
Testing
End-to-end flows of basic OCI operations on an existing bundle are tested in the
OCI group of the e2e suite, e2e/oci
.
Launcher Flow
The Launcher
type connects the standard singularity CLI actions
(run/shell/exec), to execution of an OCI container in a native bundle. Invoked
with the --oci
flag, this is in contrast to running a Singularity format
container, with Singularity's own runtime engine.
spec_linux.go
Provides a minimal OCI runtime spec, that will form the basis of container
execution that is roughly comparable to running a native singularity container
with --compat
(--containall
).
mounts_linux.go
Provides code handling the addition of required mounts to the OCI runtime spec.
process_linux.go
Provides code handling configuration of container process execution, including user mapping.
launcher_linux.go
Implements Launcher.Exec
, which is called from the CLI layer. It will:
- Create a temporary bundle directory.
- Use
pkg/ocibundle/native
to retrieve the specified image, and extract it in the temporary bundle. - Configure the container by creating an appropriate runtime spec.
- Call the interactive OCI Run function to execute the container with
crun
orrunc
.
Namespace Considerations
An OCI container started via Launch.Exec
as a non-root user always uses at
least one user namespace.
The user namespace is created prior to calling runc
or crun
, so we'll call
it an outer user namespace.
Creation of this outer user namespace is via using the RunNS
function, instead
of Run
. The RunNS
function executes the Singularity starter
binary, with a
minimal configuration of the fakeroot engine (
internal/pkg/runtime/engine/fakeroot/config
).
The starter
will create a user namespace and ID mapping, and will then execute
singularity oci run
to perform the basic OCI Run operation against the bundle
that the Launcher.Exec
function has prepared.
The outer user namespace from which runc
or crun
is called always maps the
host user id to root inside the userns.
When a container is run in --fakeroot
mode, the outer user namespace is the
only user namespace. The OCI runtime config does not request any additional
userns or ID mapping be performed by crun
/ runc
.
When a container is not run in --fakeroot
mode, the OCI runtime config for
the bundle requests that crun
/ runc
:
- Create another, inner, user namespace for the container.
- Apply an ID mapping which reverses the 'fakeroot' outer ID mapping.
I.E. when a container runs without --fakeroot
, the ID mapping is:
- User ID on host (1001)
- Root in outer user namespace (0)
- User ID in container (1001)
Testing
End-to-end testing of ßthe launcher flow is via the e2e/actions
suite. Tests
prefixed oci
.