mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 09:34:36 +08:00
fix(docker): preserve resource containers during cleanup
This commit is contained in:
1 parent
df953bdcd1
commit
d07bc9c0ff
5 files changed
+46
-5
No files matched your search
@@ -161,7 +161,7 @@ class CleanupDocker implements ShouldBeUnique
|
||||
);
|
||||
|
||||
$commands = [
|
||||
'docker container prune -f --filter "label=coolify.managed=true" --filter "label!=coolify.proxy=true" --filter "label!=coolify.type=database" --filter "label!=coolify.type=application" --filter "label!=coolify.type=service"',
|
||||
$this->buildContainerPruneCommand(),
|
||||
$imagePruneCmd,
|
||||
'docker builder prune -af',
|
||||
"docker run --rm -v {$buildxMetadataVolume}:/root/.docker/buildx -v /var/run/docker.sock:/var/run/docker.sock {$helperImageWithVersion} docker buildx prune --builder coolify-railpack -af 2>/dev/null || true",
|
||||
@@ -207,6 +207,20 @@ class CleanupDocker implements ShouldBeUnique
|
||||
return instant_remote_process([$command], $server, false, timeout: $remaining);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a command that removes stopped Coolify containers, except the proxy and the
|
||||
* containers of databases, applications and services.
|
||||
*
|
||||
* docker container prune only excludes a container that matches all of its label!= filters
|
||||
* together, so we list the stopped containers and filter them by label in the shell.
|
||||
*/
|
||||
private function buildContainerPruneCommand(): string
|
||||
{
|
||||
return "docker ps -a --filter status=created --filter status=exited --filter status=dead --filter label=coolify.managed=true --format '{{.ID}} coolify.proxy={{.Label \"coolify.proxy\"}} coolify.type={{.Label \"coolify.type\"}}' | ".
|
||||
"grep -v -E 'coolify\.proxy=true |coolify\.type=(database|application|service)$' | ".
|
||||
"awk '{print $1}' | xargs -r docker rm";
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a docker image prune command that excludes application image repositories.
|
||||
*
|
||||
|
||||
@@ -5,7 +5,7 @@ $sshCommandTimeout = (int) env('SSH_COMMAND_TIMEOUT', 3600);
|
||||
|
||||
return [
|
||||
'coolify' => [
|
||||
'version' => env('COOLIFY_VERSION') ?: '4.4.3',
|
||||
'version' => env('COOLIFY_VERSION') ?: '4.4.4',
|
||||
'helper_version' => '1.0.17',
|
||||
'railpack_version' => '0.23.0',
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.4.3"
|
||||
"version": "4.4.4"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.5-rc.1"
|
||||
|
||||
@@ -372,7 +372,7 @@ it('gives remote cleanup commands a local timeout and fails once the cleanup dea
|
||||
expect(fn () => CleanupDocker::run($server))
|
||||
->toThrow(RuntimeException::class, 'Docker cleanup did not finish within '.CleanupDocker::REMOTE_COMMANDS_DEADLINE.' seconds');
|
||||
|
||||
$sshCommands = $commands->filter(fn (string $command) => str_contains($command, 'docker container prune') || str_contains($command, 'docker image prune'))->values();
|
||||
$sshCommands = $commands->filter(fn (string $command) => str_contains($command, 'label=coolify.managed=true') || str_contains($command, 'docker image prune'))->values();
|
||||
|
||||
expect(CleanupDocker::REMOTE_COMMANDS_DEADLINE)->toBeLessThan(CleanupDocker::JOB_TIMEOUT)
|
||||
->and($sshCommands)->toHaveCount(2)
|
||||
@@ -498,3 +498,30 @@ it('scans application images with a fixed number of remote commands and keeps th
|
||||
expect($removal)->not->toContain($kept);
|
||||
}
|
||||
});
|
||||
|
||||
it('removes stopped Coolify containers but keeps the proxy, databases, applications and services', function () {
|
||||
$command = (new ReflectionMethod(CleanupDocker::class, 'buildContainerPruneCommand'))->invoke(new CleanupDocker);
|
||||
preg_match("/--format '([^']+)'/", $command, $format);
|
||||
$stoppedContainers = collect([
|
||||
['proxy', 'true', ''],
|
||||
['database', '', 'database'],
|
||||
['application', '', 'application'],
|
||||
['service', '', 'service'],
|
||||
['helper', '', ''],
|
||||
])->map(fn (array $container) => str_replace(['{{.ID}}', '{{.Label "coolify.proxy"}}', '{{.Label "coolify.type"}}'], $container, $format[1]));
|
||||
|
||||
// Fake docker on PATH: `docker ps` prints the stopped containers, `docker rm` prints what it is asked to remove
|
||||
$bin = sys_get_temp_dir().'/docker-cleanup-'.bin2hex(random_bytes(4));
|
||||
mkdir($bin);
|
||||
file_put_contents("$bin/containers", $stoppedContainers->implode("\n")."\n");
|
||||
file_put_contents("$bin/docker", "#!/bin/sh\nif [ \"\$1\" = ps ]; then cat $bin/containers; else echo \"\$@\"; fi\n");
|
||||
chmod("$bin/docker", 0755);
|
||||
|
||||
$output = shell_exec('PATH='.escapeshellarg("$bin:".getenv('PATH')).' /bin/sh -c '.escapeshellarg($command));
|
||||
|
||||
array_map('unlink', glob("$bin/*"));
|
||||
rmdir($bin);
|
||||
|
||||
expect($command)->toContain('--filter label=coolify.managed=true')
|
||||
->and(trim((string) $output))->toBe('rm helper');
|
||||
});
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.4.3"
|
||||
"version": "4.4.4"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.5-rc.1"
|
||||
|
||||
Reference in new issue
Block a user