1
0
Fork 0

Improvements to docker detection (#12062)

* Improvements to docker detection, fixes #11073

* Apply suggestions from code review

Co-authored-by: Dan Wallis <dan@wallis.nz>
pull/12090/head
Jordi Boggiano 2024-08-19 11:01:34 +02:00 committed by GitHub
parent d3d378184b
commit 9da1948585
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 46 additions and 9 deletions

View File

@ -39,3 +39,10 @@ Also note that the `exec` command will always run third party code as the user w
See the [COMPOSER_ALLOW_SUPERUSER](../03-cli.md#composer-allow-superuser) environment variable for See the [COMPOSER_ALLOW_SUPERUSER](../03-cli.md#composer-allow-superuser) environment variable for
more info on how to disable the warnings. more info on how to disable the warnings.
## Running Composer inside Docker/Podman containers
Composer makes a best effort attempt to detect that it runs inside a container and if so it will
allow running as root without any further issues. If that detection fails however you will
see warnings and plugins will be disabled unless you set the [COMPOSER_ALLOW_SUPERUSER](../03-cli.md#composer-allow-superuser)
environment variable.

View File

@ -218,11 +218,7 @@ class Application extends BaseApplication
$needsSudoCheck = !Platform::isWindows() $needsSudoCheck = !Platform::isWindows()
&& function_exists('exec') && function_exists('exec')
&& !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER') && !Platform::getEnv('COMPOSER_ALLOW_SUPERUSER')
&& (ini_get('open_basedir') || ( && !Platform::isDocker();
!file_exists('/.dockerenv')
&& !file_exists('/run/.containerenv')
&& !file_exists('/var/run/.containerenv')
));
$isNonAllowedRoot = false; $isNonAllowedRoot = false;
// Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins // Clobber sudo credentials if COMPOSER_ALLOW_SUPERUSER is not set before loading plugins

View File

@ -25,6 +25,8 @@ class Platform
private static $isVirtualBoxGuest = null; private static $isVirtualBoxGuest = null;
/** @var ?bool */ /** @var ?bool */
private static $isWindowsSubsystemForLinux = null; private static $isWindowsSubsystemForLinux = null;
/** @var ?bool */
private static $isDocker = null;
/** /**
* getcwd() equivalent which always returns a string * getcwd() equivalent which always returns a string
@ -153,12 +155,10 @@ class Platform
} }
if ( if (
!ini_get('open_basedir') !(bool) ini_get('open_basedir')
&& is_readable('/proc/version') && is_readable('/proc/version')
&& false !== stripos((string)Silencer::call('file_get_contents', '/proc/version'), 'microsoft') && false !== stripos((string)Silencer::call('file_get_contents', '/proc/version'), 'microsoft')
&& !file_exists('/.dockerenv') // Docker and Podman running inside WSL should not be seen as WSL && !self::isDocker() // Docker and Podman running inside WSL should not be seen as WSL
&& !file_exists('/run/.containerenv')
&& !file_exists('/var/run/.containerenv')
) { ) {
return self::$isWindowsSubsystemForLinux = true; return self::$isWindowsSubsystemForLinux = true;
} }
@ -175,6 +175,40 @@ class Platform
return \defined('PHP_WINDOWS_VERSION_BUILD'); return \defined('PHP_WINDOWS_VERSION_BUILD');
} }
public static function isDocker(): bool
{
if (null !== self::$isDocker) {
return self::$isDocker;
}
// cannot check so assume no
if ((bool) ini_get('open_basedir')) {
return self::$isDocker = false;
}
// .dockerenv and .containerenv are present in some cases but not reliably
if (file_exists('/.dockerenv') || file_exists('/run/.containerenv') || file_exists('/var/run/.containerenv')) {
return self::$isDocker = true;
}
// see https://www.baeldung.com/linux/is-process-running-inside-container
$cgroups = [
'/proc/self/mountinfo', // cgroup v2
'/proc/1/cgroup', // cgroup v1
];
foreach($cgroups as $cgroup) {
if (!is_readable($cgroup)) {
continue;
}
$data = file_get_contents($cgroup);
if (is_string($data) && str_contains($data, '/var/lib/docker/')) {
return self::$isDocker = true;
}
}
return self::$isDocker = false;
}
/** /**
* @return int return a guaranteed binary length of the string, regardless of silly mbstring configs * @return int return a guaranteed binary length of the string, regardless of silly mbstring configs
*/ */