Skip to main content

start_command/
docker_init_option.rs

1//! Parse and validate the opt-in init process for docker isolation
2//! (issue #244):
3//!
4//! ```text
5//! --init      run `docker run --init`, so Docker's bundled tini is PID 1
6//!             and reaps orphaned processes
7//! --no-init   keep the command as PID 1, overriding the environment default
8//! ```
9//!
10//! Without either flag, `START_COMMAND_DOCKER_INIT=1` turns it on for every
11//! docker launch on the host. The default stays off: a command that is its
12//! own supervisor keeps today's behaviour, and recovery works the same for
13//! containers started with or without it.
14
15use crate::args_parser::WrapperOptions;
16
17/// Environment variable holding the host-wide default.
18pub const DOCKER_INIT_ENV: &str = "START_COMMAND_DOCKER_INIT";
19
20/// Whether an environment value asks for an init process (1, true, yes, on).
21pub fn docker_init_from_env_value(value: Option<&str>) -> bool {
22    let value = value.unwrap_or("").trim().to_lowercase();
23    matches!(value.as_str(), "1" | "true" | "yes" | "on")
24}
25
26/// Parse `--init` / `--no-init`. Returns the number of arguments consumed.
27pub fn parse(args: &[String], index: usize, options: &mut WrapperOptions) -> usize {
28    match args[index].as_str() {
29        "--init" => {
30            options.init = Some(true);
31            1
32        }
33        "--no-init" => {
34            options.init = Some(false);
35            1
36        }
37        _ => 0,
38    }
39}
40
41/// Resolve `options.init` from the environment. See [`validate_with_env`].
42pub fn validate(options: &mut WrapperOptions) -> Result<(), String> {
43    validate_with_env(options, &|name| std::env::var(name).ok())
44}
45
46/// Resolve `options.init` to `Some(bool)`: the flag if one was given (`None`
47/// means none), otherwise the environment default for docker launches.
48/// Idempotent, because validation may run again on options it already
49/// resolved: `--no-init` (or a resolved `false`) without docker is the default
50/// anyway and is accepted.
51pub fn validate_with_env(
52    options: &mut WrapperOptions,
53    env: &dyn Fn(&str) -> Option<String>,
54) -> Result<(), String> {
55    let is_docker = options.isolated.as_deref() == Some("docker");
56    if options.init == Some(true) && !is_docker {
57        return Err("--init option is only valid with --isolated docker".to_string());
58    }
59    if options.init.is_none() {
60        options.init =
61            Some(is_docker && docker_init_from_env_value(env(DOCKER_INIT_ENV).as_deref()));
62    }
63    Ok(())
64}