Containers (Docker and Apptainer)
FLUXOS ships two container recipes under containers/ that install every
system dependency the solver links against. Compilation is deliberately
left for the user, inside a shell in the running container — this keeps
the images small, gives you a reproducible dev loop (edit source on the host,
rebuild inside the container), and drops the compiled binary straight onto
the host via a bind mount.
Recommended paths:
Docker — laptops / workstations (
containers/Dockerfile,containers/docker-compose.yml).Apptainer / Singularity — HPC clusters where Docker is not available (
containers/fluxos_apptainer.deffor CPU,containers/fluxos_apptainer_cuda.deffor GPU).
Both paths give the same four-step flow:
Install the container runtime and do a sanity check.
Build the image (dependencies only — this is cached after the first build).
Open a shell inside a container from that image.
Inside the shell, configure with CMake,
make, and run FLUXOS.
Mount layout
Both compose / .def files bind-mount the entire repository at a
single path inside the container:
Host path |
Container path |
Access |
Notes |
|---|---|---|---|
repo root ( |
|
read-write |
sources, inputs ( |
Mounting the whole repo (rather than picking individual subfolders) means
every file the simulation writes — no matter which OUTPUT_FOLDER the
modset names — lands on the host automatically. Results/,
Results_river_30h/, Results_trimesh_soil/, etc. all work without
changes to the compose / .def file.
The key CMake flag in the four-step flow is
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/work/bin (Docker) or /src/bin
(Apptainer) — it redirects the compiled binary to the bind-mounted bin/
folder so you can run it from the host as ./bin/fluxos after exiting
the shell.
Docker
1. Install Docker
macOS / Windows: install Docker Desktop (https://www.docker.com/products/docker-desktop).
Linux: install Docker Engine (https://docs.docker.com/engine/install/).
Sanity check the daemon is up:
docker --version && docker compose version
2. Build the FLUXOS dependency image
From the repo root:
docker compose -f containers/docker-compose.yml build
This produces the fluxos:latest image (~300 MB) containing CMake, GCC,
Armadillo, nlohmann/json, HDF5, OpenMP, and optionally OpenMPI (pass
--build-arg USE_MPI=ON to include it).
3. Open a shell inside the container
docker compose -f containers/docker-compose.yml run --rm fluxos
You land in /work with the host repo bind-mounted there. A baked-in
copy of the source at /opt/fluxos also ships in the image as a
fallback for image-only workflows, but the recommended path is to compile
from /work directly so host edits are picked up automatically.
4. Compile and run (inside the container shell)
cd /work && mkdir -p build && cd build
cmake -DMODE_release=ON \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/work/bin /work
make -j$(nproc)
cd /work
./bin/fluxos Working_example/modset_trimesh.json
When you exit the shell (exit / Ctrl-D) the container is removed (thanks
to --rm), but the binary at bin/fluxos, the build/ tree, and
every simulation-output file stay on the host — they were always on the
host through the bind mount.
Re-compile after editing source — no image rebuild needed
Because the repo is bind-mounted at /work, edits made on the host
(in your editor) are immediately visible inside the container. Just
re-enter the container shell and make -j$(nproc) from build/ —
no image rebuild required. Run docker compose ... build only when you
change the Dockerfile or want a fresh dependency layer.
Apptainer / Singularity (HPC)
Apptainer (the OCI-compatible successor to Singularity) is the container runtime most HPC clusters support. FLUXOS ships two recipes:
containers/fluxos_apptainer.def— CPU image (OpenMP + optional MPI).containers/fluxos_apptainer_cuda.def— NVIDIA CUDA-enabled image for GPU runs (based on annvidia/cudaimage; requires--nvat runtime).
1. Activate Apptainer
Most HPC systems ship it as an environment module:
module load apptainer # or: module load singularity
apptainer --version
On a local workstation, install from https://apptainer.org/docs/admin/main/installation.html.
2. Build the .sif image
From the repo root (or the login node of your cluster):
apptainer build fluxos.sif containers/fluxos_apptainer.def
# GPU variant (CUDA base image):
apptainer build fluxos_cuda.sif containers/fluxos_apptainer_cuda.def
Note
Apptainer does not require root to run images, but building .sif
images with --fakeroot may require admin configuration on your
cluster. When that’s a blocker, build locally on your workstation and
scp the resulting .sif file to the cluster.
3. Open a shell inside the container
Bind-mount the repo at /src so compilation output lands on the host
filesystem:
apptainer shell --bind "$PWD:/src" fluxos.sif
# GPU variant — expose the host's NVIDIA driver with --nv:
apptainer shell --nv --bind "$PWD:/src" fluxos_cuda.sif
4. Compile and run (inside the container shell)
cd /src && mkdir -p build && cd build
cmake -DMODE_release=ON \
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/src/bin /opt/fluxos
make -j$(nproc)
cd /src
./bin/fluxos Working_example/modset_trimesh.json
For CUDA GPU builds, add -DUSE_CUDA=ON; for MPI, add -DUSE_MPI=ON and
invoke with mpirun -n <N>. See High-Performance Computing (HPC) for SLURM submission templates.
Container build flags (summary)
Once inside the shell, the same CMake flags that apply to a native build apply here. Common combinations:
Goal |
CMake flags |
|---|---|
OpenMP only, regular mesh |
|
OpenMP + triangular mesh |
|
MPI + OpenMP (HPC) |
|
CUDA GPU |
|
Full hybrid (GPU + MPI + triangular) |
|
Always include
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/work/bin (Docker) or /src/bin
(Apptainer) so the binary lands on the bind-mounted host path.
Troubleshooting
“Cannot connect to the Docker daemon” — Docker Desktop is not running,
or your user is not in the docker group (Linux native install).
“apt-get update … Hash Sum mismatch” during image build — transient
mirror issue. Rerun docker compose ... build.
``cmake`` cannot find Armadillo inside the container — the image already
ships libarmadillo-dev; you most likely ran cmake from the wrong
directory. Always invoke it from /work/build (Docker) or
/src/build (Apptainer), pointing the source-tree argument at the
bind-mounted repo (/work or /src).
Binary ends up in ``build/bin/`` instead of the host ``bin/`` — you
forgot -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/work/bin (or /src/bin).
Either re-run CMake with the flag, or copy the binary manually:
cp /work/build/bin/fluxos /work/bin/.
Simulation runs but I cannot find the results — the output folder is
taken from the modset’s OUTPUT.OUTPUT_FOLDER field (e.g.
"Results_river_30h/"), resolved relative to the current working
directory at run time. Because the whole repo is bind-mounted at
/work (Docker) or /src (Apptainer), running from that path means
the results appear alongside bin/, Working_example/, and the rest
of your checkout on the host. If you cd somewhere else before running,
they land there instead.
Apptainer ``–nv`` reports “Failed to find NVIDIA driver” — the host has
no NVIDIA driver (or an incompatible version). Use the CPU .sif instead.