How to Mount a Host Directory into a Container with Apple Container

Mount a host directory into a container using container run --volume <hostPath>:<containerPath> for concise bind-mounts or --mount type=bind,source=<hostPath>,target=<containerPath> for explicit control, allowing data sharing between macOS and the Linux container filesystem.

The apple/container open-source project enables seamless data sharing by forwarding macOS host paths through a lightweight VM into the container namespace. This bind-mount capability eliminates the need to copy files, letting you edit assets on your Mac and immediately access them inside the running container. Whether you need quick directory sharing or fine-grained permission control, the tool provides two distinct CLI flags to handle host-to-container file mapping.

Using the --volume Flag for Quick Bind-Mounts

The --volume (or -v) flag offers the fastest way to mount a host directory into a container using a simple colon-separated syntax.

Syntax and Parsing

The pattern requires an absolute host path and a container destination: --volume <hostPath>:<containerPath>. When you execute a command like container run --volume ${HOME}/Desktop/assets:/content/assets <image>, the CLI parses this string into a Mount struct that is passed directly to the container runtime. This parsing logic is validated in the integration test suite at Tests/IntegrationTests/Run/TestCLIRunCommand.swift (line 344), demonstrating how the flag propagates from user input to the internal runtime API.

Permission Suffixes

By default, mounted host directories are accessed read-only. You can explicitly control permissions by appending suffixes to the mount string:

  • :ro – Explicit read-only (default behavior)
  • :rw – Read-write access allowing modifications from within the container

For example, to allow the container to write changes back to your Desktop folder, use --volume "${HOME}/Desktop/assets:/content/assets:rw".

Using the --mount Flag for Explicit Control

When you need clearer semantics or additional mount options, the --mount flag provides a comma-separated key-value syntax that mirrors Docker's mount specification.

Detailed Key-Value Configuration

The --mount format explicitly declares parameters: --mount type=bind,source=<hostPath>,target=<containerPath>[,readonly]. As documented in docs/how-to.md (lines 54-60), this approach eliminates ambiguity by labeling each component (source vs. target) and supports the readonly keyword for explicit permission locking.

For instance, to mount assets as read-only using explicit syntax:

container run --rm \
    --mount type=bind,source=${HOME}/Desktop/assets,target=/content/assets,readonly \
    docker.io/python:alpine \
    ls -l /content/assets

The definitive specifications for both flags are outlined in docs/command-reference.md (lines 60-76), which defines the accepted parameters and validation rules used by the CLI.

Practical Code Examples

These commands demonstrate mounting a host directory into a container using both available syntaxes:


# 1️⃣ Simple bind‑mount using --volume (read‑only by default)

container run --rm \
    --volume "${HOME}/Desktop/assets:/content/assets" \
    docker.io/python:alpine \
    ls -l /content/assets

# 2️⃣ Bind‑mount with explicit read‑write permission

container run --rm \
    --volume "${HOME}/Desktop/assets:/content/assets:rw" \
    docker.io/python:alpine \
    cat /content/assets/link.svg

# 3️⃣ Using the more flexible --mount syntax

container run --rm \
    --mount type=bind,source=${HOME}/Desktop/assets,target=/content/assets,readonly \
    docker.io/python:alpine \
    ls -l /content/assets

Ensure the host directory exists before running these commands; replace ${HOME}/Desktop/assets with your target path.

How Bind Mounts Work Under the Hood

Both --volume and --mount flags ultimately create bind-mounts within the lightweight VM that backs the container. According to the technical overview in docs/how-to.md (lines 36-43), the container-runtime-linux component forwards the host macOS path into the VM, then attaches that directory to the container's namespace. This architecture allows the Linux container to access macOS filesystems with native performance characteristics while maintaining security isolation through the virtualization layer.

Summary

  • Use --volume for quick, concise syntax when you need immediate bind-mounts with simple permission controls (:rw or :ro).
  • Use --mount when you require explicit parameter declaration and clearer readability, especially in scripts or automation.
  • Both methods pass through the Mount struct defined in the CLI and are processed by container-runtime-linux to bridge the host VM and container namespace.
  • Default permissions are read-only; explicitly add :rw or omit readonly to allow write access.
  • Reference Tests/IntegrationTests/Run/TestCLIRunCommand.swift for implementation details on how the CLI parses these flags into runtime calls.

Frequently Asked Questions

What is the difference between --volume and --mount in Apple Container?

The --volume flag uses a concise colon-separated syntax (host:container[:mode]) optimized for quick command-line usage, while --mount employs an explicit comma-separated key-value format (type=bind,source=...,target=...) that provides clearer parameter semantics and self-documenting commands. Both create identical bind-mounts in the underlying VM, but --mount prevents accidental order swaps between source and target paths.

Are host directories mounted read-only by default?

Yes, when using --volume, host directories are mounted read-only unless you explicitly append the :rw suffix. Similarly, with --mount, you must deliberately omit the readonly keyword to allow write access from within the container. This default protects host data from accidental container-side modifications.

Can I mount individual files or only directories?

While the examples focus on directories, you can mount individual files using the same syntax. Specify the file path as the source and the desired file location in the container as the target: --volume "${HOME}/config.txt:/app/config.txt" or `--mount type=bind,source=${HOME}/config.txt,target=/app/config.txt".

How does the container runtime access macOS host paths?

The container-runtime-linux component bridges the gap by forwarding the macOS host path into the lightweight Linux VM that powers the container, then performing a bind-mount operation to attach that path to the container's mount namespace. This process is transparent to the container, which sees the host files as standard Linux filesystem entries.

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 →