I'm developing a Symfony application to backup and restore databases. My application works fine on the Symfony server, but I'm facing issues when trying to use it with my dockerized setup.
Context:
I have two PostgreSQL databases: the main one named "potter" and a backup one named "backup." I can successfully create a dump of these databases and store the SQL file in my Apache-PHP container at /var/www/var/dump/.
When I try to restore the main database to the backup, it works perfectly only when I execute the following command in my project terminal:
docker exec -it safebase-backup-1 psql -U user -d backup -f /var/www/var/dump/potter_dump_02-10-2024_14-05-08.sql
However, when I run the same command in another context (e.g., from my application), I get the following error:
The command "'docker' 'exec' '-i' 'safebase-backup-1' 'psql' '-U' 'user' '-d' 'backup' '-f' '/var/www/var/dump/potter_dump_02-10-2024_14-05-08.sql'" failed. Working directory: /var/www/public Error: proc_open(): posix_spawn() failed: No such file or directory.
Questions:
Why does the command work in the terminal but fail when executed from my application?
docker exec -it safebase-backup-1 psql -U user -d backup -f /var/www/var/dump/potter_dump_02-10-2024_14-05-08.sqlHow can I resolve the "proc_open(): posix_spawn() failed" error?
Any help or suggestions would be greatly appreciated!
Thank you!
My code:
RestoreService:
<?php
namespace App\Service;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Symfony\Component\Process\Process;
class RestoreService
{
public function restoreDatabase(string $fileName, string $databaseName): bool
{
$targetContainer = $this->getTargetContainer($databaseName);
$restoreCommand = [
'docker', 'exec', '-i', $targetContainer, 'psql', '-U', 'user', '-d', $databaseName, '-f', "/var/www/var/dump/$fileName"
];
$this->executeProcess($restoreCommand);
return true;
}
private function getTargetContainer(string $databaseName): string
{
switch ($databaseName) {
case 'potter':
return "safebase-database-1";
case 'backup':
return "safebase-backup-1";
default:
throw new \InvalidArgumentException("Database unknown : $databaseName");
}
}
private function executeProcess(array $command): void
{
$process = new Process($command);
$process->run();
if (!$process->isSuccessful()) {
throw new ProcessFailedException($process);
}
}
}
My controller :
#[Route('/backlog/restore/{id}', name: 'app_backup_restore')]
public function restoreForm(BackupLog $backupLog, ManagerRegistry $doctrine, Request $request): Response
{
$filePath = $backupLog->getFilePath();
if (!file_exists($filePath)) {
$this->addFlash('error', 'Le fichier de sauvegarde n\'existe pas.');
return $this->redirectToRoute('app_backups');
}
$databases = ['potter', 'backup'];
$form = $this->createForm(RestoreDatabaseType::class, null, ['databases' => $databases]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$databaseName = $data['database'];
try {
// Passer uniquement le nom du fichier à la méthode de restauration
$this->restoreService->restoreDatabase(basename($filePath), $databaseName);
$this->addFlash('success', 'La base de données a été restaurée avec succès.');
} catch (\Exception $e) {
$this->addFlash('error', 'Erreur lors de la restauration : ' . $e->getMessage());
}
return $this->redirectToRoute('app_backups');
}
return $this->render('backlog/restore.html.twig', [
'form' => $form->createView(),
'backupLog' => $backupLog,
]);
}