Skip to content

feat(drivers): support docker and podman config mounts#1785

Open
drew wants to merge 10 commits into
mainfrom
docker-podman-volumes
Open

feat(drivers): support docker and podman config mounts#1785
drew wants to merge 10 commits into
mainfrom
docker-podman-volumes

Conversation

@drew

@drew drew commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds driver-config mount support for local Docker and Podman sandboxes. Docker accepts existing named volumes and tmpfs mounts; Podman accepts existing named volumes, tmpfs mounts, and image mounts. Host bind mounts remain out of the driver-config schema, and NFS is supported through pre-created runtime-managed named volumes.

Related Issue

N/A. Follow-up to #1744.

Changes

  • Parse and validate per-sandbox mount config for Docker and Podman from --driver-config-json.
  • Validate Docker and Podman named volumes exist before sandbox creation.
  • Add Podman image mount support and image pull handling; keep Docker image mounts unsupported.
  • Document per-driver mount behavior in reference and sandbox management docs.

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

Signed-off-by: Drew Newberry <anewberry@nvidia.com>
@drew drew requested review from a team, derekwaynecarr, maxamillion and mrunalp as code owners June 5, 2026 20:56
@github-actions

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

drew added 2 commits June 5, 2026 14:04
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
@drew drew marked this pull request as draft June 5, 2026 21:48
@copy-pr-bot

copy-pr-bot Bot commented Jun 5, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Comment thread crates/openshell-driver-docker/src/lib.rs
Signed-off-by: Drew Newberry <anewberry@nvidia.com>
@drew

drew commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test 113bbea

Comment thread docs/reference/sandbox-compute-drivers.mdx
Comment thread crates/openshell-driver-podman/src/container.rs
@drew drew added the test:e2e Requires end-to-end coverage label Jun 9, 2026
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

Label test:e2e applied, but pull-request/1785 is at 113bbea while the PR head is 08b333d. A maintainer needs to comment /ok to test 08b333dd4c8ff2018646bb57aabe7f8abe5890c7 to refresh the mirror. Once the mirror catches up, re-run Branch E2E Checks from the Actions tab.

@drew

drew commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator Author

/ok to test f37da23

@drew drew marked this pull request as ready for review June 10, 2026 00:35
Comment on lines +1542 to +1554
#[test]
fn docker_config_reads_bind_mount_opt_in_from_driver_table() {
let file = config_file_from_toml(
r"
[openshell.drivers.docker]
enable_bind_mounts = true
",
);

let cfg = super::build_docker_config(Some(&file), None).expect("docker config");

assert!(cfg.enable_bind_mounts);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't call this a blocker, but it is strange that this test is in this file while the equivalent podman test is in lib.rs.

for reserved in [
"/opt/openshell",
"/etc/openshell/auth",
"/etc/openshell/tls",

@elezar elezar Jun 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex mentions that /etc/openshell-tls is also used at crates/openshell-sandbox/src/lib.rs:499. Should that also be added to the list? Does it make sense to reserve a wildcard like /etc/openshell*?

Comment on lines +768 to +772
for reserved in [
"/opt/openshell",
"/etc/openshell/auth",
"/etc/openshell/tls",
"/run/netns",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that we said we didn't want to share mount defintions between Docker and Podman, but it does seem as if the list of reserved sandbox paths is not driver-specific and would likely be needed for any driver that supports mounts in some form. Would pulling the normalisation and path validation into a common location make sense?

.is_some_and(|rest| rest.starts_with('/'))
}

fn proto_struct_to_json_object(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #1815 I moved this to a common package since it's applicable for any driver configs (3a9b352). At the very least it makes the diff for this PR a little smaller.

pids_limit: docker_pids_limit(config.sandbox_pids_limit)?,
device_requests: docker_gpu_device_requests(spec.gpu, &spec.gpu_device),
binds: Some(build_binds(sandbox, config)?),
mounts: (!user_mounts.is_empty()).then_some(user_mounts),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Is the !is_empty() check strictly required here? Could this just be Some(user_mounts)? Alternatively, could one just use docker_driver_mounts(template, config.enable_bind_mounts)? directly here? (Or is the intent to allow errors to be triggered earlier?)

source: String,
target: String,
#[serde(default)]
read_only: bool,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that read_only is false by default. While I understand that this is the behaviour for Docker and Podman, does it make sense to invert this for the sandboxing use case so that users need to explicitly add rw?

Comment on lines +1833 to +1847
if target.is_empty() {
return Err(Status::failed_precondition(
"mount target must not be empty",
));
}
if target.as_bytes().contains(&0) {
return Err(Status::failed_precondition(
"mount target must not contain NUL bytes",
));
}
if !target.starts_with('/') {
return Err(Status::failed_precondition(
"mount target must be an absolute container path",
));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is the same as validate_absolute_mount_source does reusing the logic make things simpler?

Comment on lines +1862 to +1866
if target == "/sandbox" {
return Err(Status::failed_precondition(
"mount target '/sandbox' is reserved for the OpenShell workspace",
));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Why not just fold /sandbox into the reserved list below? Is it because we allow mounts to paths below /sandbox?

host_gateway_ip: String::new(),
ssh_socket_path: "/run/openshell/ssh.sock".to_string(),
sandbox_pids_limit: DEFAULT_SANDBOX_PIDS_LIMIT,
enable_bind_mounts: false,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have added this flag to prevent users from adding direct host mounts by default. These are, however, still possible when creating a docker volume mapping to a local path. Should those also be gated on this flag?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:e2e Requires end-to-end coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants