Skip to content

Commit

Permalink
Support rootless docker.
Browse files Browse the repository at this point in the history
Adds support for rootless docker, and manually overriding
rootless/rootful container engines through the
`CROSS_ROOTLESS_CONTAINER_ENGINE` environment variable. If not set, it
will use the default mode for the container engine (rootful for docker,
rootless for everything else).

```bash
\# use the defaults
cross run ...
\# auto-select if using rootless (the default)
CROSS_ROOTLESS_CONTAINER_ENGINE=auto cross run ...
\# always use rootful mode
CROSS_ROOTLESS_CONTAINER_ENGINE=0 cross run ...
\# always use rootless mode
CROSS_ROOTLESS_CONTAINER_ENGINE=1 cross run ...
```

Closes #889.
  • Loading branch information
Alexhuszagh committed Jul 1, 2022
1 parent f059d1a commit 169f5a2
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ This project adheres to [Semantic Versioning](http:https://semver.org/).

## [Unreleased] - ReleaseDate

### Added
- #890 - support rootless docker via the `CROSS_ROOTLESS_CONTAINER_ENGINE` environment variable.

### Changed

- #869 - ensure cargo configuration environment variable flags are passed to the docker container.
Expand Down
59 changes: 56 additions & 3 deletions src/docker/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{env, fs};
use super::custom::Dockerfile;
use super::engine::*;
use crate::cargo::{cargo_metadata_with_args, CargoMetadata};
use crate::config::Config;
use crate::config::{bool_from_envvar, Config};
use crate::errors::*;
use crate::extensions::{CommandExt, SafeCommand};
use crate::file::{self, write_file, PathExt, ToUtf8};
Expand Down Expand Up @@ -399,8 +399,17 @@ pub(crate) fn group_id() -> String {
}

pub(crate) fn docker_user_id(docker: &mut Command, engine_type: EngineType) {
// We need to specify the user for Docker, but not for Podman.
if engine_type == EngineType::Docker {
// by default, docker runs as root so we need to specify the user
// so the resulting file permissions are for the current user.
// since we can have rootless docker, we provide an override.
let is_rootless = env::var("CROSS_ROOTLESS_CONTAINER_ENGINE")
.ok()
.and_then(|s| match s.as_ref() {
"auto" => None,
b => Some(bool_from_envvar(b)),
})
.unwrap_or_else(|| engine_type != EngineType::Docker);
if !is_rootless {
docker.args(&["--user", &format!("{}:{}", user_id(), group_id(),)]);
}
}
Expand Down Expand Up @@ -648,6 +657,50 @@ pub fn path_hash(path: &Path) -> Result<String> {
#[cfg(test)]
mod tests {
use super::*;
use crate::id;

#[test]
fn test_docker_user_id() {
let var = "CROSS_ROOTLESS_CONTAINER_ENGINE";
let old = env::var(var);
env::remove_var(var);

let rootful = format!("\"engine\" \"--user\" \"{}:{}\"", id::user(), id::group());
let rootless = "\"engine\"".to_string();

let test = |engine, expected| {
let mut cmd = Command::new("engine");
docker_user_id(&mut cmd, engine);
assert_eq!(expected, &format!("{cmd:?}"));
};
test(EngineType::Docker, &rootful);
test(EngineType::Podman, &rootless);
test(EngineType::PodmanRemote, &rootless);
test(EngineType::Other, &rootless);

env::set_var(var, "0");
test(EngineType::Docker, &rootful);
test(EngineType::Podman, &rootful);
test(EngineType::PodmanRemote, &rootful);
test(EngineType::Other, &rootful);

env::set_var(var, "1");
test(EngineType::Docker, &rootless);
test(EngineType::Podman, &rootless);
test(EngineType::PodmanRemote, &rootless);
test(EngineType::Other, &rootless);

env::set_var(var, "auto");
test(EngineType::Docker, &rootful);
test(EngineType::Podman, &rootless);
test(EngineType::PodmanRemote, &rootless);
test(EngineType::Other, &rootless);

match old {
Ok(v) => env::set_var(var, v),
Err(_) => env::remove_var(var),
}
}

mod mount_finder {
use super::*;
Expand Down

0 comments on commit 169f5a2

Please sign in to comment.