mirror of
https://github.com/systemd/systemd.git
synced 2024-11-01 00:51:24 +03:00
virt: detect Docker and Podman containers
Docker doesn't set $container, so it cannot be detected that way. Instead, we check for presence of /.dockerinit, which it creates. Podman does set $container, but some Red Hat images (in particular, Fedora images) override $container to equal "oci". So to correctly detect Podman containers, we check for presence of /run/.containerenv, which is created by Podman and is now the official way to get information about the container from within the container. Fixes https://github.com/systemd/systemd/issues/15393
This commit is contained in:
parent
46a906f414
commit
a4a9a6f7c6
@ -453,6 +453,34 @@ static const char *const container_table[_VIRTUALIZATION_MAX] = {
|
||||
|
||||
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(container, int);
|
||||
|
||||
static int detect_container_files(void) {
|
||||
unsigned i;
|
||||
|
||||
static const struct {
|
||||
const char *file_path;
|
||||
int id;
|
||||
} container_file_table[] = {
|
||||
/* https://github.com/containers/podman/issues/6192 */
|
||||
/* https://github.com/containers/podman/issues/3586#issuecomment-661918679 */
|
||||
{ "/run/.containerenv", VIRTUALIZATION_PODMAN },
|
||||
/* https://github.com/moby/moby/issues/18355 */
|
||||
/* Docker must be the last in this table, see below. */
|
||||
{ "/.dockerenv", VIRTUALIZATION_DOCKER },
|
||||
};
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(container_file_table); i++) {
|
||||
if (access(container_file_table[i].file_path, F_OK) >= 0)
|
||||
return container_file_table[i].id;
|
||||
|
||||
if (errno != ENOENT)
|
||||
log_debug_errno(errno,
|
||||
"Checking if %s exists failed, ignoring: %m",
|
||||
container_file_table[i].file_path);
|
||||
}
|
||||
|
||||
return VIRTUALIZATION_NONE;
|
||||
}
|
||||
|
||||
int detect_container(void) {
|
||||
static thread_local int cached_found = _VIRTUALIZATION_INVALID;
|
||||
_cleanup_free_ char *m = NULL, *o = NULL, *p = NULL;
|
||||
@ -530,7 +558,7 @@ int detect_container(void) {
|
||||
*/
|
||||
e = getenv("container");
|
||||
if (!e)
|
||||
goto none;
|
||||
goto check_files;
|
||||
if (isempty(e)) {
|
||||
r = VIRTUALIZATION_NONE;
|
||||
goto finish;
|
||||
@ -558,12 +586,28 @@ int detect_container(void) {
|
||||
if (r < 0) /* This only works if we have CAP_SYS_PTRACE, hence let's better ignore failures here */
|
||||
log_debug_errno(r, "Failed to read $container of PID 1, ignoring: %m");
|
||||
|
||||
none:
|
||||
/* If that didn't work, give up, assume no container manager. */
|
||||
check_files:
|
||||
/* Check for existence of some well-known files. We only do this after checking
|
||||
* for other specific container managers, otherwise we risk mistaking another
|
||||
* container manager for Docker: the /.dockerenv file could inadvertently end up
|
||||
* in a file system image. */
|
||||
r = detect_container_files();
|
||||
if (r)
|
||||
goto finish;
|
||||
|
||||
/* If none of that worked, give up, assume no container manager. */
|
||||
r = VIRTUALIZATION_NONE;
|
||||
goto finish;
|
||||
|
||||
translate_name:
|
||||
if (streq(e, "oci")) {
|
||||
/* Some images hardcode container=oci, but OCI is not a specific container manager.
|
||||
* Try to detect one based on well-known files. */
|
||||
r = detect_container_files();
|
||||
if (!r)
|
||||
r = VIRTUALIZATION_CONTAINER_OTHER;
|
||||
goto finish;
|
||||
}
|
||||
r = container_from_string(e);
|
||||
if (r < 0)
|
||||
r = VIRTUALIZATION_CONTAINER_OTHER;
|
||||
|
Loading…
Reference in New Issue
Block a user