# How to Create a Persistent Container Machine with Custom Resources in macOS

> Create a persistent container machine with custom resources in macOS. Use container machine create and set commands to define CPU and memory limits for your container.

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

---

**To create a persistent container machine with custom resources, use `container machine create` to provision the machine from an OCI image, then `container machine set` to write CPU and memory limits to disk, and restart to apply the changes.**

A **container machine** is a core feature of the `apple/container` repository that lets you run a full Linux environment on macOS. These machines are built from standard OCI images and provide **persistent storage** that survives stop/start cycles, while automatically mapping your macOS user and `$HOME` into the Linux environment. This guide demonstrates how to provision a machine and configure custom CPU and memory resources that persist across reboots.

## Understanding Container Machine Architecture

Container machines follow a simple initialization flow: an **OCI image** feeds into the **container-machine init** process (managed by systemd), which mounts a **persistent storage** directory on your host. When you modify resources, the `container machine set` command writes a JSON configuration file to `~/.container/machines/<name>/config.json`. The container runtime reads this configuration on every start, applying the requested CPU count, memory allocation, home-mount mode, and optional kernel overrides.

Because the configuration lives alongside the machine’s data in your home directory, these resource limits are fully persistent. You can stop the machine, reboot your Mac, and later run `container machine run -n <name>` to access the same environment with identical CPU and memory constraints, as documented in the quick-start examples in [[`docs/container-machine.md`](https://github.com/apple/container/blob/main/docs/container-machine.md)](https://github.com/apple/container/blob/main/docs/container-machine.md).

## Creating a Persistent Container Machine

The first step provisions the persistent storage and establishes the home directory mapping. You create the machine from any OCI image, such as `alpine:latest` or `ubuntu:latest`.

Run the following command to create a machine named `dev`:

```bash
container machine create alpine:latest --name dev

```

After creation, verify that the host integration works correctly:

```bash
container machine run -n dev whoami    # Outputs your macOS username

container machine run -n dev pwd       # Shows /home/<username> with mounted $HOME

```

## Configuring Custom Resources

Once the machine exists, you modify its resource allocation using the `set` subcommand. According to the command reference in [[`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md)](https://github.com/apple/container/blob/main/docs/command-reference.md), this writes the new configuration to disk, but the changes only take effect after a stop/start cycle.

### Setting CPU and Memory Limits

Use the `cpus` and `memory` settings to allocate hardware resources. For example, to assign 4 CPUs and 8 GiB of RAM to the `dev` machine:

```bash
container machine set -n dev cpus=4 memory=8G

```

This updates the JSON configuration stored at `~/.container/machines/dev/config.json`. The settings include:
- **`cpus`**: Integer number of virtual CPUs
- **`memory`**: Memory limit with unit suffix (`G` for GiB, `M` for MiB)

### Applying Configuration Changes

Restart the machine so the Linux kernel sees the new allocations:

```bash
container machine stop dev
container machine run -n dev

```

After restart, the machine retains these custom resources across future stops and starts because the configuration is stored persistently on disk, not in volatile runtime state.

## Verifying Resource Allocation

Confirm that the resource limits are active by checking inside the container environment:

```bash
container machine run -n dev -- nproc   # Should report 4 CPUs

container machine run -n dev -- free -h # Should show approximately 8 GiB RAM

```

These commands execute inside the persistent container machine and reflect the values stored in the machine’s configuration file.

## Advanced Configuration Options

Beyond CPU and memory, you can customize the home directory mount behavior and kernel parameters. For example, to make your home directory read-only inside the machine:

```bash
container machine set -n dev home-mount=ro
container machine stop dev
container machine run -n dev

```

Now attempts to write to `$HOME` will fail, as demonstrated in the practical examples found in [[`examples/container-machine-vscode/README.md`](https://github.com/apple/container/blob/main/examples/container-machine-vscode/README.md)](https://github.com/apple/container/blob/main/examples/container-machine-vscode/README.md).

## Summary

- **Create** a persistent machine with `container machine create <image> --name <name>` to provision OCI-based Linux environments that survive reboots.
- **Configure** custom resources using `container machine set` with parameters like `cpus=4` and `memory=8G`, which writes to `~/.container/machines/<name>/config.json`.
- **Restart** the machine to apply resource changes, as the Linux kernel only reads CPU and memory limits during initialization.
- **Verify** allocations with standard Linux tools like `nproc` and `free` executed via `container machine run`.

## Frequently Asked Questions

### What makes a container machine "persistent"?

A container machine is persistent because its filesystem and configuration are stored in a directory on your host at `~/.container/machines/<name>/`. Unlike ephemeral containers, the data survives `container machine stop` commands and host reboots. When you restart the machine, it mounts the same storage and applies the same resource limits defined in [`config.json`](https://github.com/apple/container/blob/main/config.json).

### Where is the container machine configuration stored?

The configuration is stored as a JSON file at `~/.container/machines/<name>/config.json`. This file contains the CPU count, memory limit, home-mount mode, and optional kernel overrides. The `container machine set` command modifies this file directly, ensuring settings persist across system restarts.

### Do I need to recreate the machine to change resources?

No, you do not need to recreate the machine. Use `container machine set` to update the configuration on disk, then stop and restart the machine. The resource changes take effect on the next start because the runtime reads the updated [`config.json`](https://github.com/apple/container/blob/main/config.json) during initialization. This allows you to tune resources without losing existing data in the machine's filesystem.

### Can I use any OCI image for a container machine?

Yes, you can use any standard OCI-compatible Linux image, such as `alpine:latest`, `ubuntu:latest`, or custom images. The `container machine create` command pulls and provisions the image into the persistent storage structure. The image must support the container machine's initialization system (systemd) to properly boot the Linux environment.