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

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 detects this prefix to determine the operation direction.


# 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:

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

Behind the scenes, 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 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:

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.

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.


# 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, 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 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.

XPC Communication Layer

Sources/Services/Runtime/RuntimeClient/RuntimeClient.swift defines the public API for sending copy requests. It uses route constants from RuntimeRoutes.swift (com.apple.container.runtime/copyIn and com.apple.container.runtime/copyOut) and message keys from 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 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. 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 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 (CLI), RuntimeClient.swift (XPC client), RuntimeService.swift (XPC server), and 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, 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. Both commands accept identical arguments and flags, as documented in 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.

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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →