# How to Export and Import Container Filesystems in the Apple Container Engine

> Export and import container filesystems using Apple Container Engine's container export and import CLI commands. Archive and restore container root filesystems easily.

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

---

**The Apple Container Engine provides `container export` and `container import` CLI commands that wrap XPC messages to the daemon, enabling you to archive a stopped container’s root filesystem to a tar file and restore it as a new container.**

The `apple/container` repository ships a lightweight container runtime that supports filesystem snapshots through a pair of CLI subcommands. These commands allow you to move container root filesystems between hosts or create backups by serializing the entire container contents into a tar archive. Understanding how to export and import container filesystems correctly requires knowing the underlying XPC communication pattern and temporary file handling implemented in the Swift source code.

## Exporting Container Filesystems

The `container export` command creates a portable archive of a stopped container’s root filesystem. According to the source code in [`Sources/ContainerCommands/Container/ContainerExport.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerExport.swift), this command requires the target container to be in a stopped state before the daemon will allow the operation.

### How the Export Command Works

The implementation follows a four-step workflow that ensures atomic operations and proper cleanup:

1. **Temporary directory creation**: The CLI creates a fresh temporary directory using `FileManager.default.temporaryDirectory` and writes the archive to `archive.tar` inside this location.

2. **Daemon communication**: The command constructs an `XPCMessage` with route `containerExport` and sends it via `ContainerClient.export(id:archive:)` as defined in [`Sources/Services/ContainerAPIService/Client/ContainerClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Client/ContainerClient.swift). The daemon streams the container’s root filesystem directly into the tar file.

3. **Output handling**: If you omit the `--output` flag, the command pipes the tar bytes from the temporary file to stdout, allowing Unix redirection. If you specify an output path with `-o`, the temporary file is atomically moved to that location.

4. **Cleanup**: A `defer` block removes the temporary directory regardless of success or failure, guaranteeing no stray files remain on the host.

### CLI Usage Examples

Export to stdout for redirection:

```bash
container export abc123 > abc123.tar

```

Export directly to a specific path:

```bash
container export abc123 -o /backups/abc123.tar

```

## Importing Container Filesystems

The `container import` command reverses the process, creating a new container from an existing tar archive. This functionality is implemented in [`Sources/ContainerCommands/Container/ContainerImport.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerImport.swift) and follows a similar architecture to the export command.

### How the Import Command Works

The import command creates a temporary directory for the incoming tar payload, then sends an `XPCMessage` with route `containerImport` to the daemon. As registered in `Sources/APIServer/APIServer+Start.swift`, the daemon handles this route by reading the tar payload and building a new container image from it, returning a fresh container ID that can be started immediately.

The command supports both file-based imports and stdin streams, with the same cleanup logic running after completion to remove temporary files.

### CLI Usage Examples

Import from a file:

```bash
container import abc123.tar

```

Import from stdin using the `-` shorthand:

```bash
cat abc123.tar | container import -

```

## Understanding the XPC Architecture

Both commands rely on XPC (Inter-Process Communication) to communicate with the privileged daemon. The client-side API in [`ContainerClient.swift`](https://github.com/apple/container/blob/main/ContainerClient.swift) abstracts the message construction, while `APIServer+Start.swift` registers the route handlers that map `XPCRoute.containerExport` and `XPCRoute.containerImport` to their respective implementation functions.

This architecture ensures that filesystem operations run with appropriate privileges while the CLI remains unprivileged, following the principle of least privilege common in container runtimes.

## Summary

- **Export requires stopped containers**: The daemon explicitly rejects attempts to export running containers to ensure filesystem consistency.
- **Tar format**: Both commands use standard tar archives, compatible with tools like `docker export` and `docker import`.
- **Temporary file management**: All operations use `FileManager.default.temporaryDirectory` with guaranteed cleanup via `defer` blocks.
- **Stdin support**: The import command accepts `-` to read from stdin, enabling pipeline workflows.
- **Source locations**: Export logic lives in [`ContainerExport.swift`](https://github.com/apple/container/blob/main/ContainerExport.swift), import in [`ContainerImport.swift`](https://github.com/apple/container/blob/main/ContainerImport.swift), with shared client code in [`ContainerClient.swift`](https://github.com/apple/container/blob/main/ContainerClient.swift) and daemon routes in `APIServer+Start.swift`.

## Frequently Asked Questions

### Can I export a running container?

No. The daemon returns an error if you attempt to export a container that is currently running. You must stop the container first using `container stop <id>` before calling `container export`. This restriction prevents race conditions and ensures the filesystem snapshot captures a consistent state.

### What format does the export use?

The export creates a standard tar archive containing the container’s root filesystem. This format is compatible with other container tools and can be examined using standard Unix utilities like `tar -tf archive.tar`. The archive preserves the directory structure and permissions of the original container filesystem.

### How do I import from stdin?

Use the hyphen character `-` as the file argument to read from stdin. This is useful for piped workflows: `cat backup.tar | container import -` or `ssh host 'cat container.tar' | container import -`. The command buffers the stream to a temporary file before sending it to the daemon via XPC.

### Where does the export command store temporary files?

The export command uses `FileManager.default.temporaryDirectory` to create a unique subdirectory for each operation. This typically resolves to `/tmp` or the system-designated temporary directory. Files are automatically cleaned up via a `defer` block after the operation completes, even if the command fails or is interrupted.