apple / apple/container

[Request]: `cp` command tar stream support

Open
#1,908 2 comments 4 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
49.9k
Forks
1.8k
Avg merge
1d 20h
Merged PRs (30d)
22

Description

### Feature or enhancement request details

## Request

Please add tar stream support to `container cp`, matching the common `docker cp`/`podman cp` pattern where `-` can be used as stdin/stdout for a tar archive:

```sh
container cp CONTAINER:/path -
container cp - CONTAINER:/path
```

At a minimum this would include support for uncompressed tar streams. Docker, for example, supports compressed tar stream inputs, but doesn't call that out in their API documentation so it's probably reasonable to consider it optional.

## Background

The original `cp` request was tracked in:

- #232

The basic `container copy` / `container cp` command was added by:

- #1190

However, #1190 intentionally avoided requiring tar support inside the container image by using guest-agent copy operations. That solves ordinary file/directory copy, but it does not cover the tar stream mode described in the original issue.

The earlier discussion in #232 called out the main blockers for tar stream support:

- https://github.com/apple/container/issues/232#issuecomment-3063076085
- https://github.com/apple/container/issues/232#issuecomment-3064247728

Those comments described an intended design where one side creates a tar archive, streams it through the vminit/vminitd boundary, and the receiving side unpacks it. They also noted that Swift lacks standard library support for tar operations and that the existing `ContainerizationArchive` library depends on native libraries that were not available in the Swift Linux SDK build used for `vminitd`:

```text
ld.lld: error: unable to find library -lbz2
ld.lld: error: unable to find library -llzma
ld.lld: error: unable to find library -larchive
```

## Why tar stream support matters

While basic `cp` operations can transfer file contents, they only work with files that exist on the host filesystem and can end up preserving host-side metadata such as ownership and permissions which may not be correct in the container. Tar streams allow copying in files from memory and give full control over the mode and ownership of the files in the container. Effectively the tar stream can be thought of as a dynamic image layer applied to the container filesystem. This is something that makes `cp` much more powerful than a basic bind mount.Combined with the fact that `cp` is applied _after_ volume are attached, it's the only way to reliably inject files into a container without worrying that they'll be shadowed by a volume mount.

Basic `cp`, bind mounts, and init container volumes are not a suitable alternative because they can leak host-side metadata, shadow image contents, or require container-specific entrypoint wrapper logic. Relying on `tar` inside the target image is also not sufficient because minimal images may not include a tar binary.

We make heavy use of `cp` tar stream support in the Aspire orchestration framework (https://github.com/microsoft/aspire) to inject certificates and config files into containers with the correct ownership and permissions. We want to add the Apple container runtime as a supported backend for Aspire on macOS, but lack of tar stream support in `container cp` is a blocker for that work. We're tracking features required for parity with our Docker and Podman support in a tracking issue on our core orchestration repo: https://github.com/microsoft/dcp/issues/206.

## Proposed behavior

Support `-` as a tar stream source or destination:

```sh
# stream a tar archive out
container cp my-container:/some/path - > files.tar

# stream a tar archive in and extract it
container cp - my-container:/some/destination < files.tar
```

Suggested initial scope:

- uncompressed tar only
- regular files
- directories
- symlinks
- basic modes
- uid/gid where possible
- safe path handling: reject absolute paths, `..` traversal, and malformed headers
- clear error for compressed tar streams or unsupported tar features

Future optional scope:

- gzip/zstd/etc stream filters
- hardlinks
- sparse files
- xattrs/ACLs
- broader GNU/PAX compatibility

## Implementation options

There seem to be two possible implementation paths (as called out in the original `cp` support issue).

### Option 1: Swift tar implementation

Implement enough tar reader/writer support in Swift for the required uncompressed tar subset.

Pros:

- avoids new native dependencies in `vminitd`
- keeps the guest runtime build simpler
- supports the minimum Docker-compatible tar stream behavior
- compression can be layered later as optional stream filters
- avoids depending on tools inside the container image

Cons:

- introduces new archive parsing/extraction code
- needs careful security review for path traversal, symlinks, ownership, and overwrite behavior
- needs compatibility tests for tar variants such as ustar/pax
- may duplicate some functionality already available through `ContainerizationArchive`

### Option 2: enable native libarchive support for vminitd

Update the vminitd/Linux SDK build so `ContainerizationArchive` can be used on the guest side.

Pros:

- reuses existing archive infrastructure
- likely broader tar compatibility
- compression and other archive features may become easier to support
- avoids maintaining a separate tar implementation

Cons:

- adds native dependency/build complexity
- requires packaging or linking `libarchive`, `libbz2`, `liblzma`, etc.
- increases maintenance surface for dependency updates and CVEs
- may be heavier than needed if the required feature is only uncompressed tar streams

### Code of Conduct

- [x] I agree to follow this project's Code of Conduct

Contributor guide

Open the contributing guide

Research direction

Start with the existing container cp implementation from #1190 and the vminit/vminitd boundary, then review the linked #232 discussion about archive handling and ContainerizationArchive. Completion should cover uncompressed tar input and output for -, including regular files, directories, symlinks, modes, uid/gid, and safe path rejection, with clear errors for compressed or unsupported streams.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
backend, cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.