-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathContainer.php
More file actions
136 lines (115 loc) · 4 KB
/
Copy pathContainer.php
File metadata and controls
136 lines (115 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?php
declare(strict_types=1);
namespace DrevOps\EnvironmentDetector\Stacks;
use DrevOps\EnvironmentDetector\Contexts\Drupal;
use DrevOps\EnvironmentDetector\Contexts\DrupalContextualizerInterface;
/**
* Container stack (generic containerisation).
*
* @package DrevOps\EnvironmentDetector\Stacks
*/
class Container extends AbstractStack implements DrupalContextualizerInterface {
/**
* {@inheritdoc}
*/
public const ID = 'container';
/**
* Conventional internal service hostnames used across Docker Compose stacks.
*
* @var string[]
*/
public const SERVICE_HOSTS = ['web', 'app', 'webserver', 'nginx', 'apache', 'apache2'];
/**
* Cached result of the container probe, shared across the run.
*/
protected static ?bool $cachedIsContainer = NULL;
/**
* {@inheritdoc}
*/
public function active(): bool {
return $this->isContainer();
}
/**
* Check whether the environment runs inside a container.
*
* @return bool
* TRUE if running inside a container, FALSE otherwise.
*/
public function isContainer(): bool {
// Containerisation is fixed for the lifetime of the process, so the probe
// is computed once per run and the result reused on any later call. A
// subclass overriding isContainer() opts out of the cache and is probed on
// its own terms.
return self::$cachedIsContainer ??= $this->detectContainer();
}
/**
* Reset the cached container probe so the next detection re-runs it.
*/
public static function resetCache(): void {
self::$cachedIsContainer = NULL;
}
/**
* Probe the host for the signals that indicate a container.
*
* @return bool
* TRUE if running inside a container, FALSE otherwise.
*/
protected function detectContainer(): bool {
// No single marker reliably proves containerisation across runtimes, so
// several independent signals are probed in turn until one matches.
if (getenv('DOCKER') !== FALSE) {
return TRUE;
}
if (getenv('container') !== FALSE) {
return TRUE;
}
// @codeCoverageIgnoreStart
if (file_exists('/.dockerenv') || file_exists('/.dockerinit')) {
return TRUE;
}
$cgroup = '';
if (is_readable('/proc/1/cgroup')) {
$content = file_get_contents('/proc/1/cgroup');
$cgroup = is_string($content) ? $content : '';
}
// @codeCoverageIgnoreEnd
return str_contains($cgroup, 'docker') || str_contains($cgroup, 'kubepods');
}
/**
* {@inheritdoc}
*/
public function contextualizeDrupal(Drupal $context): void {
$settings = &$context->settings;
// Internal service hostnames, reachable container-to-container. The
// SERVICE_HOSTS env var contributes extra comma-separated hosts on top of
// the built-in allowlist. Every host is escaped before joining the
// alternation: the pattern feeds the security-sensitive
// trusted_host_patterns, so a host carrying a regex metacharacter must not
// be able to widen the match.
$hosts = static::SERVICE_HOSTS;
$extra = getenv('SERVICE_HOSTS');
if (is_string($extra)) {
foreach (explode(',', $extra) as $host) {
$host = trim($host);
if ($host !== '') {
$hosts[] = $host;
}
}
}
$hosts = array_map(static fn(string $host): string => preg_quote($host, '#'), $hosts);
$settings['trusted_host_patterns'][] = '^(' . implode('|', array_unique($hosts)) . ')$';
// The site's local development URL, reduced to its host: a port, path, or
// credentials would never match Drupal's host-only trusted-host check.
$url = getenv('LOCALDEV_URL');
if (is_string($url) && $url !== '') {
$host = parse_url($url, PHP_URL_HOST);
if (!is_string($host) || $host === '') {
// A bare host with no scheme parses as a path, so retry with one.
$host = parse_url('http://' . ltrim($url, '/'), PHP_URL_HOST);
}
if (is_string($host) && $host !== '') {
$settings['trusted_host_patterns'][] = '^' . preg_quote($host, '#') . '$';
}
}
}
}