Skip to content
Docs

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.

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:

  1. Config-level volumes — apply to every container (default: [$HOME])
  2. Per-command volumes — listed in the manifest volumes field
  3. 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/output

Running 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/redis

With no_default_volumes, only the explicitly listed volumes (and auto-mounted argument paths) are included. Config-level volumes like $HOME are skipped.

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.

When you activate with --strict-env, containers start with a clean environment. Only explicitly allowlisted variables are passed through:

bulker activate --strict-env demo
bulker exec --strict-env demo -- samtools --version

The allowlist merges two sources:

  1. Config-level envvars — apply to every container (default: [DISPLAY])
  2. Per-command envvars — listed in the manifest envvars field

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 sufficient

In --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-env allowlist.

    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-env mode (in normal mode, all env vars are passed anyway).

  • BULKER_EXTRA_DOCKER_ARGS — arbitrary additional flags passed to docker 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 handles volumes and envvars differently from Docker:

  • $HOME is 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 --env flags are needed — the behavior matches bulker’s default of passing all host env vars.
  • With --strict-env, bulker adds --cleanenv to strip the inherited environment, then passes each allowlisted variable via --env NAME=VALUE.

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.

When you run a shimlinked command, bulker inspects every argument before passing it to the container. For each argument:

  1. Flags are skipped. Any argument starting with - is never examined for path content.
  2. If the path exists on the filesystem: bulker canonicalizes it to an absolute path (resolving .., symlinks, and relative components) and mounts its parent directory.
  3. 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.
  4. 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.

Reading an existing file:

samtools view /projects/data/sample1.bam

Bulker 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.bam

Bulker 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.

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.