# How to Create and Manage Named Volumes with Apple's Container Runtime

> Learn to create and manage named volumes using Apple's container runtime. Discover volume creation commands, size options, journaling modes, and label support.

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

---

**Apple's container runtime stores named volumes as sparse disk images under `/volumes/<name>/` and validates names against the regex `^[A-Za-z0-9][A-Za-z0-9_.-]*$`, supporting creation via the `container volume create` command with options for size, ext4 journaling mode, and labels.**

Apple's open-source container runtime (available in the `apple/container` repository) implements volumes as first-class resources that persist data outside the container's root filesystem. Unlike ephemeral container layers, named volumes survive container restarts and can be mounted into multiple containers simultaneously. Understanding how to create and manage named volumes with Apple's container runtime is essential for running stateful workloads and maintaining data persistence across container lifecycles.

## Understanding Volume Storage and Naming Constraints

### Volume Storage Implementation

The runtime treats each volume as a **sparse disk image** (`volume.img`) stored in a dedicated host directory under `/volumes/<name>/`. This design keeps volume data isolated from the container's root filesystem while maintaining efficient storage allocation through sparseness.

### Name Validation Rules

Volume names must conform to strict validation rules enforced by `VolumeStorage.volumeNamePattern` in [`Sources/ContainerResource/Volume/VolumeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Volume/VolumeConfiguration.swift) (lines 36-45). The pattern `^[A-Za-z0-9][A-Za-z0-9_.-]*$` requires names to start with an alphanumeric character, permits periods, hyphens, and underscores in subsequent characters, and limits the total length to **255 bytes**. Both the client-side **Parser** (lines 457-459) and the server-side **VolumesService** invoke `VolumeStorage.isValidVolumeName` to enforce these constraints before any creation operation.

## Creating Named Volumes with the CLI

When you execute `container volume create`, the CLI forwards the request to the daemon's **VolumesService**, which validates the name and generates the backing image via `createVolumeImage(for:name:sizeInBytes:journal:)` (lines 290-322 in [`Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift)).

### Basic Volume Creation

Create a simple named volume with default parameters:

```bash
container volume create myvolume

```

### Configuring Size and Journaling Options

The runtime supports several create-time options for the default `local` driver:

- **`--label <key=value>`**: Attaches arbitrary metadata to the volume.
- **`--opt size=<size>`**: Specifies the volume size (e.g., `10g`). Overridden by the `-s` flag if both are provided.
- **`--opt journal=<mode>`**: Configures the ext4 journaling mode. Valid modes are `ordered`, `writeback`, or `journal`. You can optionally specify a journal size (e.g., `journal=writeback:64m`).
- **`-s <size>`**: Explicit size in bytes (supports human-readable formats like `10g`).

Create a 10 GiB volume with ordered journaling:

```bash
container volume create \
    --opt journal=ordered \
    --opt size=10g \
    myvolume

```

Create a volume with writeback journaling and a 64 MiB journal:

```bash
container volume create \
    --opt journal=writeback:64m \
    myvolume

```

### Working with Anonymous Volumes

When you mount a path without specifying a volume name (e.g., `container run -v /data`), the runtime generates an **anonymous** volume name via `VolumeStorage.generateAnonymousVolumeName()` (lines 52-55 in [`Sources/ContainerResource/Volume/VolumeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Volume/VolumeConfiguration.swift)). These names follow the pattern `anon-<uuid>` and persist after the container exits. They are not automatically garbage collected and require manual deletion.

Create and reuse an anonymous volume:

```bash

# Creates an anonymous volume automatically

container run -v /data alpine

# Retrieve the generated name

VOL=$(container volume list -q | grep anon)

# Mount the same anonymous volume in a new container

container run -v $VOL:/data alpine

```

## Managing Volume Lifecycle

### Listing and Inspecting Volumes

List all volumes in human-readable format:

```bash
container volume list

```

Inspect a specific volume's metadata and configuration in JSON:

```bash
container volume inspect myvolume --format json

```

### Deleting and Pruning Unused Volumes

Delete a specific volume permanently:

```bash
container volume delete myvolume

```

**Note:** Deletion fails if the volume is currently attached to any container, regardless of whether the container is running or stopped.

Remove all unused volumes (those not attached to any container) with a single command:

```bash
container volume prune

```

## Programmatic Volume Creation with Swift

You can also create volumes programmatically using the `ContainerAPIService` client. The Swift API accepts a `JournalConfig` enum for journaling modes and handles the underlying validation and image creation:

```swift
import ContainerAPIService

let client = ContainerAPIClient()
do {
    try client.createVolume(
        name: "myvolume",
        sizeInBytes: 10 * 1024 * 1024 * 1024,  // 10 GiB
        journal: .ordered                       // EXT4.JournalConfig
    )
    print("Volume created successfully")
} catch {
    print("Failed to create volume: \(error)")
}

```

This client method invokes the same `createVolumeImage` validation logic (lines 319-320) and sparse image generation used by the CLI.

## Summary

- **Volumes** are stored as sparse disk images (`volume.img`) under `/volumes/<name>/` on the host.
- **Name validation** uses the regex `^[A-Za-z0-9][A-Za-z0-9_.-]*$` with a 255-byte limit, enforced by `VolumeStorage.isValidVolumeName`.
- **Create volumes** using `container volume create` with `--opt` flags for `size=` and `journal=` (supporting modes `ordered`, `writeback`, and `journal`).
- **Anonymous volumes** (generated via `generateAnonymousVolumeName`) persist after container exit and must be deleted manually.
- **Deletion** requires the volume to be unattached from all containers, verified by the **VolumesService** before removal.

## Frequently Asked Questions

### What is the naming convention for volumes in Apple's container runtime?

Volume names must match the pattern `^[A-Za-z0-9][A-Za-z0-9_.-]*$` and cannot exceed 255 bytes. This means names must start with a letter or number, can contain periods, hyphens, and underscores, but cannot contain spaces or other special characters. The validation is implemented in [`Sources/ContainerResource/Volume/VolumeConfiguration.swift`](https://github.com/apple/container/blob/main/Sources/ContainerResource/Volume/VolumeConfiguration.swift) and enforced by both the client parser and server-side `VolumesService`.

### How do I configure ext4 journaling when creating a volume?

Use the `--opt journal=<mode>` flag where `<mode>` is `ordered`, `writeback`, or `journal`. You can optionally specify a journal size by appending `:<size>` (e.g., `journal=writeback:64m`). This configuration is processed by the `createVolumeImage` method in [`Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Volumes/VolumesService.swift) when formatting the underlying sparse image.

### Are anonymous volumes automatically deleted when a container stops?

No. Anonymous volumes—generated via `VolumeStorage.generateAnonymousVolumeName()` with the `anon-<uuid>` prefix when using `-v /path` without a named volume—persist on the host after the container exits. You must manually delete them using `container volume delete` or `container volume prune` if they are no longer needed.

### Why does volume deletion fail with an error about attached containers?

The runtime prevents deletion of volumes that are currently mounted by any container, including stopped containers. This safety check is enforced by the **VolumesService** before executing the delete operation. You must first remove all containers using the volume (running or stopped) before the delete command will succeed.