How to Set Up Bind Mounts for Host Directory Access in Containers

Bind mounts in the apple/container CLI expose host directories inside containers by mapping the type=bind specification to a Virtio-FS device through the Parser.mount method.

The apple/container repository provides a lightweight, VM-based container runtime that supports Docker-compatible bind mounts. While the user-facing API resembles standard container tools, the underlying implementation converts bind specifications into Virtio-FS mounts for efficient host-to-guest file sharing. This guide explains how to configure bind mounts using the CLI and how the Parser.mount routine in Sources/Services/ContainerAPIService/Client/Parser.swift processes these requests.

Understanding the Parser.mount Implementation

The mount parsing logic resides in Parser.swift and handles both --mount and --volume flags. When the CLI receives a mount string, the Parser.mount method (lines 54‑71) splits the input into key-value pairs, normalizes synonyms like src to source and dst to destination, and validates each directive.

Converting Bind to Virtio-FS

The critical transformation occurs in the type branch (lines 94‑100). When the parser encounters type=bind, it rewrites the type to virtiofs internally:

case "type":
    if val == "bind" {
        val = "virtiofs"          // bind is mapped to virtiofs
    }

This conversion allows the runtime to expose host directories via a Virtio-FS device rather than traditional kernel bind mounts, which is necessary for the VM-based architecture.

Resolving Host Paths

The source directive handling (lines 130‑143) supports both absolute and relative paths. For bind mounts, the code resolves relative paths against a base path provided by the CLI:

case "source":
    switch type {
    case "virtiofs", "bind":
        let url = basePath?.appending(path: val).standardizedFileURL ?? URL(filePath: val)
        let absolutePath = url.absoluteURL.path

The parser validates that the path exists and is a directory, throwing a ContainerizationError with the message "path '…' does not exist" if validation fails (lines 138‑143).

Runtime Handling of Bind Mounts

After parsing, the mount description becomes a Filesystem value with .type = .virtiofs, source = <host-absolute-path>, and destination = <container-path>. The container runtime translates this into a Virtio-FS device that the VM presents as a regular filesystem at the requested mount point.

Because Virtio-FS is a shared filesystem, changes made inside the container immediately reflect on the host and vice versa. This provides the same semantics as traditional bind mounts while operating within a lightweight virtual machine.

Command-Line Usage

The apple/container CLI supports two syntaxes for bind mounts, both ultimately invoking the same parser code.

Using the --mount Syntax

The recommended approach uses comma-separated key-value pairs:

container run --mount type=bind,source=$HOME/project/src,target=/app/src alpine:latest ls /app/src

This explicit syntax supports advanced options like read-only flags.

Using the --volume Shorthand

The --volume flag provides Docker-compatible shorthand:

container run --volume $HOME/project/src:/app/src alpine:latest ls /app/src

Both forms resolve to identical internal representations through Parser.mount.

Practical Code Examples

Mount the Current Working Directory

Expose the current folder at /work inside the container:

container run --mount type=bind,src=.,dst=/work alpine:latest \
    sh -c "ls /work && echo 'Hello from host'"

Mount an Absolute Host Path

Use environment variables to mount specific host directories:

HOST_DATA=/Users/fido/projects/data
container run --mount type=bind,source=${HOST_DATA},target=/data \
    python:3.12-alpine python -c "import pathlib; print(list(pathlib.Path('/data').iterdir()))"

Create a Read-Only Bind Mount

Append the ro flag to prevent container modifications:

container run --mount type=bind,src=$HOME/config,target=/etc/config,ro \
    nginx:stable-alpine nginx -t

Use Volume Shorthand for Logs

The short syntax works identically for read-only mounts:

container run --volume $HOME/logs:/var/log:ro \
    busybox:latest cat /var/log/syslog

Bind Mount During Build

The container build command also supports bind mounts for accessing build context files:

container build --mount type=bind,src=.,target=/src .

Verification Through Testing

The test suite in Tests/ContainerAPIClientTests/ParserTest.swift validates the parsing behavior. Lines 34‑48 verify that relative paths resolve correctly against a temporary directory, while lines 40‑55 confirm absolute paths remain unmodified. Error handling tests (lines 85‑94) ensure that non-existent paths or files (rather than directories) raise ContainerizationError with descriptive messages.

Summary

  • Bind mounts map host directories into containers using the --mount type=bind or --volume syntax.
  • The Parser.mount method in Parser.swift converts bind specifications to Virtio-FS mounts for VM compatibility.
  • The parser resolves both relative and absolute paths, validating that the source exists and is a directory.
  • Changes are bidirectional and immediate due to the shared Virtio-FS filesystem.
  • Both container run and container build subcommands support bind mounts.

Frequently Asked Questions

What is the difference between --mount and --volume in apple/container?

Both flags invoke the same Parser.mount logic, but --mount uses explicit comma-separated key-value pairs (e.g., type=bind,source=/host,target=/container), while --volume uses Docker-style shorthand (e.g., /host:/container). The --mount syntax supports additional options like read-only flags directly in the key-value format.

How does apple/container handle relative paths in bind mounts?

The parser resolves relative paths against the CLI's current working directory. In Parser.swift (lines 130‑143), the code uses basePath?.appending(path: val).standardizedFileURL to convert relative sources into absolute URLs before mounting, ensuring the Virtio-FS device receives a fully qualified host path.

Why does the implementation convert bind mounts to Virtio-FS?

The apple/container runtime uses a lightweight virtual machine architecture rather than running containers directly on the host kernel. Converting type=bind to virtiofs (lines 94‑100) allows the host directory to be shared through a Virtio-FS device, providing the same semantics as traditional bind mounts while maintaining the security and isolation benefits of VM-based containerization.

What happens if the host directory does not exist?

The Parser.mount method validates the source path and throws a ContainerizationError with the message "path '…' does not exist" if the directory is missing (lines 138‑143). This validation occurs before the runtime attempts to create the Virtio-FS device, preventing runtime failures inside the VM.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →