Volumes and Environment Variables
Bulker containers run in isolation by default. To give a container access to host directories or environment variables, you configure volumes (directory mounts) and envvars (environment variable pass-through). These can be set globally in the config, per-command in the manifest, or at runtime via environment variables.
How volumes work
Section titled “How volumes work”Volumes are directories mounted into the container so the containerized command can read and write files on the host. Each volume maps the same path inside and outside the container — there is no separate source:target mapping. This means file paths work identically whether a command is containerized or running natively.
Bulker builds the final volume list for each command by merging three layers:
- Config-level volumes — apply to every container (default:
[$HOME]) - Per-command volumes — listed in the manifest
volumesfield - Auto-mounted argument paths — directories detected from command-line arguments
For example, given this config and manifest:
# In bulker config:# volumes: [$HOME]
# In manifest:manifest: name: genomics-tools commands: - command: samtools docker_image: quay.io/biocontainers/samtools:1.9--h91753b0_8 volumes: - /data/references - /scratch/outputRunning samtools view /projects/sample1.bam produces a volume list of:
$HOME(from config)/data/references(from manifest)/scratch/output(from manifest)/projects(auto-mounted from the argument path)
Each becomes --volume "/path:/path" in Docker or -B "/path:/path" in Apptainer. Duplicate paths are removed automatically.
Opting out of default volumes with no_default_volumes
Section titled “Opting out of default volumes with no_default_volumes”Some containers conflict with the default $HOME mount — for example, containers that expect their own home directory layout. Use no_default_volumes: true to skip config-level volumes entirely:
- command: redis-server docker_image: redis:7 no_default_volumes: true volumes: - /var/lib/redisWith no_default_volumes, only the explicitly listed volumes (and auto-mounted argument paths) are included. Config-level volumes like $HOME are skipped.
How envvars work
Section titled “How envvars work”By default, bulker passes all host environment variables into Docker containers. This mirrors how native commands work — your LANG, DISPLAY, EDITOR, and other env vars are available inside the container without any configuration.
A small set of Docker-managed variables (PATH, HOME, HOSTNAME) and bulker internal variables (anything starting with BULKER) are excluded automatically.
The --strict-env allowlist
Section titled “The --strict-env allowlist”When you activate with --strict-env, containers start with a clean environment. Only explicitly allowlisted variables are passed through:
bulker activate --strict-env demobulker exec --strict-env demo -- samtools --versionThe allowlist merges two sources:
- Config-level
envvars— apply to every container (default:[DISPLAY]) - Per-command
envvars— listed in the manifestenvvarsfield
Example:
manifest: name: gui-tools commands: - command: firefox docker_image: jess/firefox envvars: - DISPLAY - XAUTHORITY - XDG_RUNTIME_DIR - command: samtools docker_image: quay.io/biocontainers/samtools:1.9--h91753b0_8 # No extra envvars needed -- config default (DISPLAY) is sufficientIn --strict-env mode, firefox gets DISPLAY (from config, deduplicated) + XAUTHORITY + XDG_RUNTIME_DIR (from manifest). samtools gets just DISPLAY (from config). In normal mode, all host env vars are passed regardless of these fields.
See Strict Environments for more details.
Runtime overrides with environment variables
Section titled “Runtime overrides with environment variables”Two environment variables let you add volumes or envvars at runtime without editing manifests:
-
BULKER_EXTRA_ENVVARS— comma-separated list of additional environment variable names to add to the--strict-envallowlist.export BULKER_EXTRA_ENVVARS="AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_DEFAULT_REGION"This is useful for temporary credentials or session-specific variables that should not be baked into manifests. Only has effect in
--strict-envmode (in normal mode, all env vars are passed anyway). -
BULKER_EXTRA_DOCKER_ARGS— arbitrary additional flags passed todocker run. Not specific to volumes or envvars, but can be used for ad-hoc mounts or env overrides when the structured fields are not sufficient.
Apptainer differences
Section titled “Apptainer differences”Apptainer handles volumes and envvars differently from Docker:
$HOMEis filtered out of the bind list because Apptainer binds the home directory automatically. Other volumes use-B "/path:/path"instead of--volume.- Environment variables are inherited by default in Apptainer (the container sees the host environment). In normal mode, no explicit
--envflags are needed — the behavior matches bulker’s default of passing all host env vars. - With
--strict-env, bulker adds--cleanenvto strip the inherited environment, then passes each allowlisted variable via--env NAME=VALUE.
Auto-mounting argument paths
Section titled “Auto-mounting argument paths”Bulker automatically detects file and directory paths in command-line arguments and mounts their parent directories as volumes. This means that in many cases you do not need to add explicit volumes entries — just pass the file path as an argument and bulker handles the rest.
How it works
Section titled “How it works”When you run a shimlinked command, bulker inspects every argument before passing it to the container. For each argument:
- Flags are skipped. Any argument starting with
-is never examined for path content. - If the path exists on the filesystem: bulker canonicalizes it to an absolute path (resolving
.., symlinks, and relative components) and mounts its parent directory. - If the path does not exist but its parent directory does: bulker mounts the parent directory and rewrites the argument to its absolute form. This handles output files that do not yet exist — the output directory is mounted so the command can write there.
- Otherwise: the argument passes through unchanged.
Directories detected this way are merged into the volume list alongside config-level and manifest-level volumes. Duplicates (e.g., two files in the same directory) are removed automatically.
Examples
Section titled “Examples”Reading an existing file:
samtools view /projects/data/sample1.bamBulker resolves /projects/data/sample1.bam, determines that /projects/data is the parent directory, and adds it to the volume list automatically.
Writing an output file that does not exist yet:
samtools view input.bam -o /results/output.bam-o starts with - so it is skipped. /results/output.bam does not exist yet, but /results does, so /results is mounted and the argument is rewritten to the absolute path. The command can write the output file inside the container and it appears on the host.
Using relative paths or symlinks:
samtools view ../data/sample.bamBulker resolves ../data/sample.bam to an absolute path, mounts the parent directory, and passes the absolute path into the container. The user does not need to think about path translation.
When you still need explicit volumes
Section titled “When you still need explicit volumes”Auto-mount only fires when an argument is actually passed on the command line. If your tool needs access to a directory that is not passed as an argument — for example, a hard-coded reference data path baked into the container’s logic, or a shared database location — declare it in the manifest volumes field or in the global bulker config.