-
Notifications
You must be signed in to change notification settings - Fork 172
feat: support copying from containers #871
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
DCjanus
wants to merge
6
commits into
testcontainers:main
Choose a base branch
from
DCjanus:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
beadbd2
feat: support copying from containers
DCjanus 47c9776
Merge branch 'testcontainers:main' into main
DCjanus 4fe5939
feat: enhance documentation for file copying and data handling
DCjanus 7830e29
fix(copy): stream first tar entry and simplify docs
DCjanus 0d6b1fc
test(copy-file-from): cover directory extraction error
DCjanus 6e4c82b
Merge branch 'main' into main
DCjanus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| # Files and Mounts | ||
|
|
||
| Rust Testcontainers lets you seed container filesystems before startup, collect artifacts produced inside containers, and bind host paths at runtime. The APIs deliver smooth ergonomics while staying idiomatic to Rust. | ||
|
|
||
| ## Copying Files Into Containers (Before Startup) | ||
|
|
||
| Use `ImageExt::with_copy_to` to stage files or directories before the container starts. Content can come from raw bytes or host paths: | ||
|
|
||
| ```rust | ||
| // Example: copying inline bytes and directories into a container | ||
| use testcontainers::{GenericImage, WaitFor}; | ||
|
|
||
| let project_assets = std::path::Path::new("tests/fixtures/assets"); | ||
| let image = GenericImage::new("alpine", "latest") | ||
| .with_wait_for(WaitFor::seconds(1)) | ||
| .with_copy_to("/opt/app/config.yaml", br#"mode = "test""#.to_vec()) | ||
| .with_copy_to("/opt/app/assets", project_assets); | ||
| ``` | ||
|
|
||
| Everything is packed into a TAR archive, preserving nested directories. The helper accepts either `Vec<u8>` or any path-like value implementing `CopyDataSource`. | ||
| Note: file permissions and symbolic links follow Docker’s default TAR handling. | ||
|
|
||
| ## Copying Files From Containers (After Execution) | ||
|
|
||
| Use `copy_file_from` to pull data produced inside the container: | ||
|
|
||
| ```rust | ||
| // Example: copying a file from a running container to the host | ||
| use tempfile::tempdir; | ||
| use testcontainers::{GenericImage, WaitFor}; | ||
|
|
||
| #[tokio::test] | ||
| async fn copy_example() -> anyhow::Result<()> { | ||
| let container = GenericImage::new("alpine", "latest") | ||
| .with_cmd(["sh", "-c", "echo '42' > /tmp/result.txt && sleep 10"]) | ||
| .with_wait_for(WaitFor::seconds(1)) | ||
| .start() | ||
| .await?; | ||
|
|
||
| let destination = tempdir()?.path().join("result.txt"); | ||
| container | ||
| .copy_file_from("/tmp/result.txt", destination.as_path()) | ||
| .await?; | ||
| assert_eq!(tokio::fs::read_to_string(&destination).await?, "42\n"); | ||
| Ok(()) | ||
| } | ||
| ``` | ||
|
|
||
| - `copy_file_from` streams file contents into any destination implementing `CopyFileFromContainer` (for example `&Path` or `&mut Vec<u8>`). When the requested path is not a regular file you’ll receive a `CopyFromContainerError`. | ||
| - Targets like `Vec<u8>` and filesystem paths overwrite existing data: vectors are cleared before writing, and files are truncated or recreated if they already exist. | ||
| - To capture the contents in memory: | ||
| ```rust | ||
| let mut bytes = Vec::new(); | ||
| container.copy_file_from("/tmp/result.txt", &mut bytes).await?; | ||
| ``` | ||
|
|
||
| The blocking `Container` type provides the same `copy_file_from` API. | ||
|
|
||
| ## Using Mounts for Writable Workspaces | ||
|
|
||
| When a bind or tmpfs mount fits better than copy semantics, use the `Mount` helpers: | ||
|
|
||
| ```rust | ||
| // Example: mounting a host directory for read/write access | ||
| use std::path::Path; | ||
| use testcontainers::core::{mounts::Mount, AccessMode, MountType}; | ||
|
|
||
| let host_data = Path::new("/var/tmp/integration-data"); | ||
| let mount = Mount::bind(host_data, "/workspace") | ||
| .with_mode(AccessMode::ReadWrite) | ||
| .with_type(MountType::Bind); | ||
|
|
||
| let image = GenericImage::new("python", "3.13") | ||
| .with_mount(mount) | ||
| .with_cmd(["python", "/workspace/run.py"]); | ||
| ``` | ||
|
|
||
| Bind mounts share host state directly. Tmpfs mounts create ephemeral in-memory storage useful for scratch data or caches. | ||
|
|
||
| ## Selecting an Approach | ||
|
|
||
| - **Copy before startup** — for deterministic inputs. | ||
| - **Copy from containers** — to capture build artifacts, logs, or test fixtures produced during a run. | ||
| - **Use mounts** — when containers need to read/write large amounts of data efficiently without re-tarring. | ||
|
|
||
| Mixing these tools keeps tests hermetic (isolated and reproducible) while letting you inspect outputs locally. | ||
| Document each choice in code so teammates know whether data is ephemeral (`tmpfs`), seeded once (`with_copy_to`), or captured for later assertions (`copy_file_from`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.