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

> Learn to set up bind mounts for host directory access in containers using apple/container. Map directories directly into your container environment for seamless development.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-06-18

---

**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`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/Parser.swift) processes these requests.

## Understanding the Parser.mount Implementation

The mount parsing logic resides in [`Parser.swift`](https://github.com/apple/container/blob/main/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:

```swift
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:

```swift
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

```bash
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:

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

```

## Verification Through Testing

The test suite in [`Tests/ContainerAPIClientTests/ParserTest.swift`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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`](https://github.com/apple/container/blob/main/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.