is_container/
lib.rs

1//! Check if the process is running inside a container.
2//!
3//! # Examples
4//!
5//! ```
6//! use is_container::is_container;
7//!
8//! if is_container() {
9//!     println!("Running inside a container");
10//! }
11//! ```
12//!
13//! # Inspired
14//!
15//! - [How to determine if a process runs inside lxc/Docker?](https://stackoverflow.com/questions/20010199/how-to-determine-if-a-process-runs-inside-lxc-docker)
16//! - [sindresorhus/is-inside-container](https://github.com/sindresorhus/is-inside-container)
17
18use std::fs;
19
20use once_cell::sync::Lazy;
21
22fn has_docker_env() -> bool {
23    fs::metadata("/.dockerenv").is_ok()
24}
25
26fn has_container_env() -> bool {
27    fs::metadata("/run/.containerenv").is_ok()
28}
29
30fn has_cgroup_v1() -> bool {
31    fs::read_to_string("/proc/1/cgroup").map_or(false, |contents| {
32        contents.contains("docker") || contents.contains("lxc")
33    })
34}
35
36fn has_mountinfo() -> bool {
37    fs::read_to_string("/proc/1/mountinfo").map_or(false, |contents| {
38        // See https://man7.org/linux/man-pages/man5/proc.5.html
39        //
40        // The file contains lines of the form:
41        // 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue
42        // (1)(2)(3)   (4)   (5)      (6)      (7)   (8) (9)   (10)         (11)
43        contents.lines().any(|line| {
44            line.split_whitespace()
45                .nth(3)
46                .map_or(false, |mnt1| mnt1.contains("docker") || mnt1.contains("lxc"))
47        })
48    })
49}
50
51/// The main function provided by this crate. See crate documentation for more information.
52pub fn is_container() -> bool {
53    static CACHED_RESULT: Lazy<bool> =
54        Lazy::new(|| has_docker_env() || has_container_env() || has_mountinfo() || has_cgroup_v1());
55
56    *CACHED_RESULT
57}