# Container Machine vs Regular Container Commands: Architecture and Usage Guide

> Discover the key differences between container machines and regular container commands. Learn about persistent Linux environments versus ephemeral, single-process workloads to optimize your usage.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: architecture
- Published: 2026-07-08

---

**Container machines provide persistent, VM-like Linux environments with init systems and surviving state, while regular container commands execute ephemeral, single-process workloads that exit after completion.**

The Apple Container framework (`apple/container`) offers two distinct execution models for containerized workloads on macOS. While **regular container commands** handle transient, single-purpose containers, **container machines** deliver full Linux environments that bridge the gap between macOS and traditional containerized development.

## What Is a Container Machine?

A **container machine** is a lightweight virtual machine that boots an OCI image with its init system (such as `systemd`), creating a persistent Linux environment. Unlike ephemeral containers, machines maintain their root filesystem, user data, and configuration across reboots, enabling long-running services and development workflows that require a full Linux host.

According to the source code in [`Sources/ContainerCommands/Machine/MachineCreate.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineCreate.swift), the `container machine create` command initializes this VM-like environment, while [`Sources/ContainerPersistence/MachineConfig.swift`](https://github.com/apple/container/blob/main/Sources/ContainerPersistence/MachineConfig.swift) defines the persistent configuration structure that stores CPU, memory, and mount settings.

## What Are Regular Container Commands?

**Regular container commands** (such as `container run`, `exec`, and `build`) operate on ephemeral OCI containers designed for short-lived workloads. These containers start a specified process as PID 1, run until completion, and then exit—destroying their runtime state unless explicitly committed to a new image. They share the container runtime but do not provide a persistent OS instance or init system.

## Key Architectural Differences

### Persistence and State Management

Container machines survive stop/start cycles. You can halt a machine with `container machine stop` and resume later with `container machine run`, preserving all installed packages and configuration changes.

Regular containers are ephemeral by default. Stopping a regular container destroys its runtime state, and while the filesystem can be saved as a new image, the container itself cannot be resumed.

### Init System and Service Management

Machines boot the image's init system (`/sbin/init`), making `systemd`-managed services work out-of-the-box. This enables running databases, web servers, and other background services that require proper signal handling and service management.

Regular containers run the specified entrypoint directly as PID 1 without an init system or service manager. Signals are forwarded to the process, but no PID 1 reaper handles zombie processes automatically.

### User Identity and File System Mapping

Machines automatically map the macOS user's UID/GID and `$HOME` directory into the Linux environment at `/home/<user>`, enabling seamless file editing between macOS and the Linux environment.

Regular containers default to running as `root` (or a specified UID via `-u`), requiring manual volume mounts (`-v` or `--mount`) to share files between macOS and the container.

## Lifecycle Commands Comparison

Container machines use a dedicated command set implemented across several Swift source files:

- **Creation and deletion**: `container machine create` and `container machine delete` (implemented in [`Sources/ContainerCommands/Machine/MachineCreate.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineCreate.swift))
- **Execution**: `container machine run` (implemented in [`Sources/ContainerCommands/Machine/MachineRun.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineRun.swift))
- **Configuration**: `container machine set` for persistent resource allocation (implemented in [`Sources/ContainerCommands/Machine/MachineSet.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineSet.swift))
- **Inspection**: `container machine inspect`, `list`, and `logs`

The server-side logic for these operations resides in [`Sources/Services/MachineAPIService/Server/MachinesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Server/MachinesService.swift), while the CLI communicates via [`Sources/Services/MachineAPIService/Client/MachineClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Client/MachineClient.swift).

Regular container commands follow standard OCI conventions:
- `container run`, `exec`, `start`, `stop`, `rm`
- `container build` for image creation
- `container image` management commands

## Resource Configuration Models

**Machine resources** are configured persistently via `container machine set`, modifying values stored in [`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift):

```bash

# Configure machine with 4 CPUs and 8GB RAM (effective after restart)

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

```

**Container resources** are supplied per-invocation and apply only to that specific execution:

```bash

# Launch ephemeral container with limited resources

container run -it --cpus 2 --memory 2G alpine:latest sh

```

## Practical Usage Examples

### Creating and Running a Container Machine

```bash

# Create a machine named "dev" from Alpine

container machine create alpine:latest --name dev

# Start an interactive shell (user matches macOS host)

container machine run -n dev

# Run a specific command inside the persistent machine

container machine run -n dev uname -a

```

### Running Regular Ephemeral Containers

```bash

# One-off Ubuntu container with shell

container run -it ubuntu:latest /bin/bash

# Detached web server container

container run -d --name web -p 8080:80 nginx:latest

```

### Systemd Services in Machines

```bash

# Start PostgreSQL inside a machine with systemd

container machine run -n dev -- systemctl start postgresql

# Query the database

container machine run -n dev -- psql -U postgres -c "SELECT version();"

```

## Source Code Architecture

The machine abstraction is implemented through several key components:

- [`Sources/ContainerCommands/Machine/MachineCreate.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineCreate.swift): Handles VM initialization and boot configuration
- [`Sources/ContainerCommands/Machine/MachineRun.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineRun.swift): Manages command execution within running machines
- [`Sources/ContainerCommands/Machine/MachineSet.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Machine/MachineSet.swift): Persents configuration changes to [`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift)
- [`Sources/Services/MachineAPIService/Server/MachinesService.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Server/MachinesService.swift): Server-side lifecycle management (create, delete, list)
- [`Sources/Services/MachineAPIService/Client/MachineClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/MachineAPIService/Client/MachineClient.swift): Client interface between CLI and machine API

Documentation references include [`docs/container-machine.md`](https://github.com/apple/container/blob/main/docs/container-machine.md) for user-facing concepts and [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md) for complete CLI verb listings.

## Summary

- **Container machines** provide persistent, VM-like Linux environments with init system support, surviving reboots, and automatic macOS user/home directory mapping.
- **Regular container commands** execute ephemeral, single-process containers designed for short-lived workloads, builds, and isolated tool execution.
- Machines boot OCI images with init systems (enabling `systemd` services), while regular containers run entrypoints directly without service management.
- Resource configuration for machines persists across restarts via [`MachineConfig.swift`](https://github.com/apple/container/blob/main/MachineConfig.swift), whereas regular containers accept resource limits per-invocation only.
- Development environments requiring long-running services or full Linux distros should use machines; CI/CD tasks and one-off commands suit regular containers.

## Frequently Asked Questions

### Can I run systemd services using regular container commands?

No. Regular container commands execute the specified entrypoint directly as PID 1 without an init system. To run `systemd` services, you must use a **container machine**, which boots the image's init system (`/sbin/init`) and provides the service management infrastructure required by tools like `systemctl`.

### How does user mapping differ between machines and regular containers?

Container machines automatically map the macOS user's UID, GID, and `$HOME` directory into the Linux environment at `/home/<user>`, enabling seamless file editing across macOS and Linux boundaries. Regular containers default to running as `root` and require manual volume mounts with explicit UID/GID flags to achieve similar file sharing.

### What happens to my data when I stop a machine versus a regular container?

When you stop a container machine using `container machine stop`, the root filesystem, installed packages, and user data persist and remain available when you subsequently run `container machine run`. Regular containers lose their runtime state when stopped; only committed layer changes survive, and you cannot resume the same container instance after removal.

### Does container machine support nested virtualization?

Yes. Container machines support nested virtualization on Apple Silicon M3 and later processors, configurable via `container machine set`. This enables running additional virtualization workloads (such as Docker inside the machine or other nested hypervisors) within the persistent Linux environment, a capability not available in regular ephemeral containers.