mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
fix: resolve Docker validation race conditions and sudo prefix bug
- Fix sudo prefix bug: Use word boundary matching to prevent 'do' keyword from matching 'docker' commands - Add ensureProxyNetworksExist() helper to create networks before docker compose up - Ensure networks exist synchronously before dispatching async proxy startup to prevent race conditions - Update comprehensive unit tests for sudo parsing (50 tests passing) This resolves issues where Docker commands failed to execute with sudo on non-root servers and where proxy networks were not created before the proxy container started. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,37 @@ function connectProxyToNetworks(Server $server)
|
||||
|
||||
return $commands->flatten();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures all required networks exist before docker compose up.
|
||||
* This must be called BEFORE docker compose up since the compose file declares networks as external.
|
||||
*
|
||||
* @param Server $server The server to ensure networks on
|
||||
* @return \Illuminate\Support\Collection Commands to create networks if they don't exist
|
||||
*/
|
||||
function ensureProxyNetworksExist(Server $server)
|
||||
{
|
||||
['allNetworks' => $networks] = collectDockerNetworksByServer($server);
|
||||
|
||||
if ($server->isSwarm()) {
|
||||
$commands = $networks->map(function ($network) {
|
||||
return [
|
||||
"echo 'Ensuring network $network exists...'",
|
||||
"docker network ls --format '{{.Name}}' | grep -q '^{$network}$' || docker network create --driver overlay --attachable $network",
|
||||
];
|
||||
});
|
||||
} else {
|
||||
$commands = $networks->map(function ($network) {
|
||||
return [
|
||||
"echo 'Ensuring network $network exists...'",
|
||||
"docker network ls --format '{{.Name}}' | grep -q '^{$network}$' || docker network create --attachable $network",
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
return $commands->flatten();
|
||||
}
|
||||
|
||||
function extractCustomProxyCommands(Server $server, string $existing_config): array
|
||||
{
|
||||
$custom_commands = [];
|
||||
|
||||
@@ -23,38 +23,51 @@ function shouldChangeOwnership(string $path): bool
|
||||
function parseCommandsByLineForSudo(Collection $commands, Server $server): array
|
||||
{
|
||||
$commands = $commands->map(function ($line) {
|
||||
if (
|
||||
! str(trim($line))->startsWith([
|
||||
'cd',
|
||||
'command',
|
||||
'echo',
|
||||
'true',
|
||||
'if',
|
||||
'fi',
|
||||
'for',
|
||||
'do',
|
||||
'done',
|
||||
'while',
|
||||
'until',
|
||||
'case',
|
||||
'esac',
|
||||
'select',
|
||||
'then',
|
||||
'else',
|
||||
'elif',
|
||||
'break',
|
||||
'continue',
|
||||
'#',
|
||||
])
|
||||
) {
|
||||
return "sudo $line";
|
||||
$trimmedLine = trim($line);
|
||||
|
||||
// All bash keywords that should not receive sudo prefix
|
||||
// Using word boundary matching to avoid prefix collisions (e.g., 'do' vs 'docker', 'if' vs 'ifconfig', 'fi' vs 'find')
|
||||
$bashKeywords = [
|
||||
'cd',
|
||||
'command',
|
||||
'echo',
|
||||
'true',
|
||||
'if',
|
||||
'fi',
|
||||
'for',
|
||||
'done',
|
||||
'while',
|
||||
'until',
|
||||
'case',
|
||||
'esac',
|
||||
'select',
|
||||
'then',
|
||||
'else',
|
||||
'elif',
|
||||
'break',
|
||||
'continue',
|
||||
'do',
|
||||
];
|
||||
|
||||
// Special case: comments (no collision risk with '#')
|
||||
if (str_starts_with($trimmedLine, '#')) {
|
||||
return $line;
|
||||
}
|
||||
|
||||
if (str(trim($line))->startsWith('if')) {
|
||||
return str_replace('if', 'if sudo', $line);
|
||||
// Check all keywords with word boundary matching
|
||||
// Match keyword followed by space, semicolon, or end of line
|
||||
foreach ($bashKeywords as $keyword) {
|
||||
if (preg_match('/^'.preg_quote($keyword, '/').'(\s|;|$)/', $trimmedLine)) {
|
||||
// Special handling for 'if' - insert sudo after 'if '
|
||||
if ($keyword === 'if') {
|
||||
return preg_replace('/^(\s*)if\s+/', '$1if sudo ', $line);
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $line;
|
||||
return "sudo $line";
|
||||
});
|
||||
|
||||
$commands = $commands->map(function ($line) use ($server) {
|
||||
|
||||
Reference in New Issue
Block a user