setName("docker:db:export") ->setDescription("Export a database") ->addOption("mysql", null, InputOption::VALUE_NONE, "Export from a MySQL database") ->addOption("dsn", null, InputOption::VALUE_REQUIRED, "Database DSN") ->addOption("service", null, InputOption::VALUE_REQUIRED, "Service name in stack") ->addOption("database", null, InputOption::VALUE_REQUIRED, "Database name") ->addOption("output", "o", InputOption::VALUE_REQUIRED, "Output to file instead of stdout") ; } protected function execute(InputInterface $input, OutputInterface $output) { $docker = get_plugin("com.noccy.docker"); $service = $input->getOption("service"); $dsn = $input->getOption("dsn"); if ($service) { $stack = $docker->getComposeStack(); if ($input->getOption("mysql")) { $dbtype = 'mysql'; } else { $services = $stack->getServiceNames(); if (!in_array($service, $services)) { $output->writeln("Invalid service {$service}. Valid are ".join(", ", $services).""); return Command::INVALID; } $image = $stack->getService($service)->getImage(); if (preg_match('/(mysql|mariadb)/i', $image)) { $dbtype = 'mysql'; $env = $stack->getService($service)->getEnvironment(); $database = $env['MYSQL_DATABASE']??null; if ($dbpass = $env['MYSQL_ROOT_PASSWORD']??null) { $dbuser = 'root'; } else { $dbuser = $env['MYSQL_USER']??null; $dbpass = $env['MYSQL_PASSWORD']??null; } } else { $output->writeln("Unable to determine database type from service"); return Command::INVALID; } } $database = $database ?? $input->getOption("database"); if (empty($database)) { $output->writeln("No --database specified"); return Command::INVALID; } switch ($dbtype) { case 'mysql': $cmd = sprintf("mysqldump -u%s -p%s %s", $dbuser, $dbpass, $database); break; } $this->exportFromService($service, $cmd, $output, $input->getOption("output")); } elseif ($dsn) { $url = parse_url($dsn); if (empty($url)) { $output->writeln("Bad database DSN {$dsn}. Should look like mysql://user:pass@host:port/database"); return Command::INVALID; } } return Command::SUCCESS; } private function exportFromService(string $service, string $command, OutputInterface $output, ?string $outfile=null) { $cmd = sprintf("docker-compose exec -T %s %s", $service, $command); if ($outfile) { $cmd .= " > ".escapeshellarg($outfile); } $output->writeln(sprintf("→ %s", $cmd)); passthru($cmd); } }