# How to Copy Files Between Host and Running Containers in apple/container

> Easily copy files between your host and running containers using the container copy command with the container_id:path syntax. Transfer files efficiently now.

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

---

**Use the `container copy` (or `container cp`) CLI command to transfer files and directories to or from running containers by specifying paths with the `container_id:path` syntax.**

The `apple/container` project provides a native macOS container runtime with built-in support for bi-directional file copying. Understanding how to copy files between host and running containers is essential for configuration management, log extraction, and data migration workflows.

## Using the container copy Command

The CLI exposes file copying through two equivalent commands: `container copy` and its short alias `container cp`. Both support copying files in either direction—into a container (**copy-in**) or out of a container (**copy-out**)—depending on which argument includes the container ID prefix.

The command syntax requires exactly one argument to specify a container using the format `container_id:path`. The CLI parser in [`ContainerCopy.swift`](https://github.com/apple/container/blob/main/ContainerCopy.swift) detects this prefix to determine the operation direction.

```bash

# Copy from host to container (copy-in)

container cp ./local-file.txt mycontainer:/app/data/

# Copy from container to host (copy-out)

container cp mycontainer:/var/log/app.log ./host-logs/

```

## Copy Files Into a Running Container

When the source path is on the host and the destination includes a container ID, the CLI constructs an XPC request with the route `RuntimeRoutes.copyIn`. This triggers the runtime to stream the file into the container's sandbox.

### Basic File Copy

Copy a single configuration file from the current working directory into a running container:

```bash
container cp ./config.json mycontainer:/etc/app/config.json

```

Behind the scenes, [`ContainerCopy.swift`](https://github.com/apple/container/blob/main/ContainerCopy.swift) builds an `XPCMessage` containing `RuntimeKeys.sourcePath` set to `"./config.json"` and `RuntimeKeys.destinationPath` set to `"/etc/app/config.json"`. The request is sent via [`RuntimeClient.swift`](https://github.com/apple/container/blob/main/RuntimeClient.swift) to the XPC server running inside the container.

### Directory Copy with Options

Copy an entire directory while automatically creating parent directories and setting specific permissions:

```bash
container cp --create-parents --mode 0755 ./my-data mycontainer:/var/data/

```

The `--create-parents` flag maps to `RuntimeKeys.createParents` in the XPC message, while `--mode` sets `RuntimeKeys.fileMode` (defaulting to `0o644` if unspecified). The runtime service validates that the container is running before invoking `Container.copyIn` in [`ContainersService.swift`](https://github.com/apple/container/blob/main/ContainersService.swift).

## Copy Files From a Running Container to Host

To extract files from a container, place the container reference in the source position. The CLI detects the `container_id:` prefix and routes the request through `RuntimeRoutes.copyOut`.

```bash

# Copy a log file from container to host

container cp mycontainer:/var/log/application.log ./logs/

# Copy entire directory tree from container

container cp mycontainer:/app/output ./local-backup/

```

In [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift), the incoming XPC request validates that the container is active, then forwards to `Container.copyOut`. The implementation uses the host's `FileManager` to read from the container's sandbox and write to the host destination path.

## How It Works Under the Hood

The file copy operation involves four distinct layers in the `apple/container` architecture:

### CLI Parsing and Routing

[`Sources/ContainerCommands/Container/ContainerCopy.swift`](https://github.com/apple/container/blob/main/Sources/ContainerCommands/Container/ContainerCopy.swift) handles argument parsing and direction detection. It examines arguments for the `container_id:` pattern to distinguish between copy-in and copy-out operations. The parser constructs the appropriate `XPCMessage` with route identifiers defined in [`RuntimeRoutes.swift`](https://github.com/apple/container/blob/main/RuntimeRoutes.swift).

### XPC Communication Layer

[`Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift`](https://github.com/apple/container/blob/main/Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift) defines the public API for sending copy requests. It uses route constants from [`RuntimeRoutes.swift`](https://github.com/apple/container/blob/main/RuntimeRoutes.swift) (`com.apple.container.runtime/copyIn` and `com.apple.container.runtime/copyOut`) and message keys from [`RuntimeKeys.swift`](https://github.com/apple/container/blob/main/RuntimeKeys.swift) including:
- `sourcePath`: Origin file path
- `destinationPath`: Target file path  
- `fileMode`: Optional permission bits
- `createParents`: Boolean for directory creation

### Runtime Service Handling

[`Sources/Services/RuntimeLinux/Server/RuntimeService.swift`](https://github.com/apple/container/blob/main/Sources/Services/RuntimeLinux/Server/RuntimeService.swift) receives the XPC requests. For copy-in operations, it verifies the container state and forwards to the container API; for copy-out, it performs symmetric validation. If the container is not running, it returns the error: `cannot copyIn: container is not running`.

### File System Operations

The actual file transfer occurs in [`Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift`](https://github.com/apple/container/blob/main/Sources/Services/ContainerAPIService/Server/Containers/ContainersService.swift). The `Container` object implements `copyIn` and `copyOut` methods that bridge the host's `FileManager` with the container's sandboxed file system, respecting mode bits and parent directory creation flags.

## Key Constraints and Requirements

- **Container must be running**: The XPC handler in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) rejects copy requests if the target container is stopped.
- **One side must reference a container**: The command validates that exactly one argument uses the `container_id:path` syntax; otherwise it fails with "no source path supplied".
- **Automatic directory creation**: By default, parent directories are created automatically unless disabled with flags.
- **Permission preservation**: File modes can be explicitly set via the `--mode` flag during copy-in operations.

## Summary

- Use `container cp` or `container copy` to transfer files between host and running containers in the `apple/container` runtime.
- Specify the container side using the `container_id:path` syntax to determine copy direction.
- The implementation spans [`ContainerCopy.swift`](https://github.com/apple/container/blob/main/ContainerCopy.swift) (CLI), [`RuntimeClient.swift`](https://github.com/apple/container/blob/main/RuntimeClient.swift) (XPC client), [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift) (XPC server), and [`ContainersService.swift`](https://github.com/apple/container/blob/main/ContainersService.swift) (file operations).
- The container must be running; the runtime validates container state before executing copy operations.

## Frequently Asked Questions

### Can I copy files to a stopped container?

No. According to the implementation in [`RuntimeService.swift`](https://github.com/apple/container/blob/main/RuntimeService.swift), the XPC handler explicitly checks container state and returns the error `cannot copyIn: container is not running` if the target container is not active. You must start the container first using `container start` before copying files.

### What is the difference between `container cp` and `container copy`?

There is no functional difference. `cp` is a short alias for `copy`, defined in the command structure within [`ContainerCopy.swift`](https://github.com/apple/container/blob/main/ContainerCopy.swift). Both commands accept identical arguments and flags, as documented in [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md).

### How do I preserve file permissions when copying?

Use the `--mode` flag followed by an octal value (e.g., `--mode 0755`) when copying files into a container. This sets the `RuntimeKeys.fileMode` key in the XPC message. When copying out, permissions are preserved automatically by the `FileManager` implementation in [`ContainersService.swift`](https://github.com/apple/container/blob/main/ContainersService.swift).

### Can I copy files directly between two containers?

No, the current implementation requires one side of the transfer to be a host path. The CLI parser in [`ContainerCopy.swift`](https://github.com/apple/container/blob/main/ContainerCopy.swift) validates that exactly one argument contains the `container_id:` prefix. To transfer between containers, first copy from the source container to a host temporary location, then copy from that location to the destination container.