Ejemplo n.º 1
0
 public function fileGenerate()
 {
     $config = $this->getConfig();
     if (true === isset($config['stages'])) {
         $stages = $config['stages'];
     } else {
         $stages = ['local' => ['services' => []]];
     }
     foreach ($stages as $stageName => $stage) {
         $compose = ['version' => '2'];
         if (true === isset($config['volumes']) || true === isset($stage['volumes'])) {
             if (false === isset($config['volumes'])) {
                 $config['volumes'] = [];
             }
             if (false === isset($stage['volumes'])) {
                 $stage['volumes'] = [];
             }
             $compose['volumes'] = array_merge_recursive($config['volumes'], $stage['volumes']);
         }
         if (true === isset($config['services']) || true === isset($stage['services'])) {
             if (false === isset($config['services'])) {
                 $config['services'] = [];
             }
             if (false === isset($stage['services'])) {
                 $stage['services'] = [];
             }
             $services = array_merge_recursive($config['services'], $stage['services']);
             $links = [];
             foreach ($services as $key => $value) {
                 $links[$key] = isset($value['links']) ? $value['links'] : [];
             }
             try {
                 $result = \App\Helpers\Dependency::sort($links);
             } catch (\Exception $e) {
                 throw new \Peanut\Console\Exception($e);
             }
             $compose['services'] = [];
             foreach ($result as $serviceName) {
                 if (false === isset($services[$serviceName]['labels'])) {
                     $services[$serviceName]['labels'] = [];
                 }
                 $services[$serviceName]['labels'] += ['com.docker.bootapp.service' => $serviceName, 'com.docker.bootapp.name' => $this->getContainerName($serviceName), 'com.docker.bootapp.project' => $this->getProjectName()];
                 if (true === isset($services[$serviceName]['environment']['DOMAIN'])) {
                     $services[$serviceName]['labels']['com.docker.bootapp.domain'] = $services[$serviceName]['environment']['DOMAIN'];
                     if (false === strpos($services[$serviceName]['environment']['DOMAIN'], ' ')) {
                         $services[$serviceName]['labels']['com.docker.bootapp.domain'] = $services[$serviceName]['environment']['DOMAIN'];
                     } else {
                         throw new \Peanut\Console\Exception('domain name not valid');
                     }
                 }
                 if (true === isset($services[$serviceName]['container_name'])) {
                     $services[$serviceName]['container_name'] = $this->getContainerName($serviceName);
                 }
                 $compose['services'][$serviceName] = $services[$serviceName];
             }
         }
         if (true === isset($config['networks']) || true === isset($stage['networks'])) {
             if (false === isset($config['networks'])) {
                 $config['networks'] = [];
             }
             if (false === isset($stage['networks'])) {
                 $stage['networks'] = [];
             }
             $compose['networks'] = array_merge_recursive($config['networks'], $stage['networks']);
         }
         foreach ($compose['services'] as $service_name => $service) {
             if (true === isset($service['environment_from'])) {
                 foreach ($service['environment_from'] as $from_name => $from) {
                     foreach ($from as $env_name) {
                         $env_alias = preg_split('/:/D', $env_name);
                         if (true === isset($env_alias[1])) {
                             $compose['services'][$service_name]['environment'][$env_alias[1]] = $compose['services'][$from_name]['environment'][$env_alias[0]];
                         } else {
                             $compose['services'][$service_name]['environment'][$name] = $compose['services'][$env_alias[0]]['environment'][$env_alias[0]];
                         }
                     }
                 }
                 unset($compose['services'][$service_name]['environment_from']);
             }
         }
         foreach ($compose['services'] as $service_name => &$service) {
             if (true === isset($service['environment']) && $service['environment']) {
                 foreach ($service['environment'] as $key => &$value) {
                     if ($key == 0 && is_null($value)) {
                         unset($service['environment'][$key]);
                     } elseif (true === is_array($value)) {
                         $value = "'" . json_encode($value, JSON_UNESCAPED_SLASHES) . "'";
                     }
                 }
             } else {
                 unset($service['environment']);
             }
         }
         \App\Helpers\Yaml::dumpFile(getcwd() . '/docker-compose.' . $stageName . '.yml', $compose);
     }
 }
Ejemplo n.º 2
0
 /**
  * @return array
  */
 public function setConfig()
 {
     $this->config = \App\Helpers\Yaml::parseFile($this->configFileName);
 }
Ejemplo n.º 3
0
 /**
  * @param $stageName
  */
 public function Containers($mode, $isPull)
 {
     $machineName = $this->getMachineName();
     $projectName = $this->getProjectName();
     if (!$projectName) {
         echo PHP_EOL;
         while (true) {
             $inputProjectName = $this->ask('Please project a name : ');
             $command = ['docker', 'ps', '-aq', '--filter="label=com.docker.bootapp.project=' . $inputProjectName . '"'];
             $existsCount = count($this->process($command, ['print' => false])->toArray());
             if (0 == $existsCount) {
                 break;
             } else {
                 echo 'Name invalid. ';
             }
         }
         $this->config = ['project_name' => $inputProjectName] + $this->config;
         \App\Helpers\Yaml::dumpFile($this->configFileName, $this->config);
         $projectName = $this->getProjectName();
     }
     $stageName = $this->getStageName();
     $machineName = $this->getMachineName();
     $compose = \App\Helpers\Yaml::parseFile(getcwd() . '/docker-compose.' . $stageName . '.yml');
     echo \Peanut\Console\Color::text('machine | ', 'white') . $machineName . PHP_EOL;
     echo \Peanut\Console\Color::text('project | ', 'white') . $projectName . PHP_EOL;
     echo \Peanut\Console\Color::text('stage   | ', 'white') . $stageName . PHP_EOL;
     $checkBuild = false;
     $checkPull = false;
     foreach ($compose['services'] as $serviceName => &$service) {
         if (true === isset($service['name'])) {
             $name = $service['name'];
         } else {
             $name = $serviceName;
         }
         $service['org_name'] = $name;
         $service['name'] = $this->getContainerName($name);
         if (true === isset($service['build'])) {
             $checkBuild = true;
         } elseif (true === isset($service['image'])) {
             $checkPull = true;
         }
     }
     // break the reference with the last element
     unset($service);
     if ($checkPull && $isPull) {
         echo \Peanut\Console\Color::text('pull    | ', 'white');
         foreach ($compose['services'] as $serviceName => $service) {
             if (true === isset($service['image'])) {
                 $command = ['docker', 'pull', $service['image']];
                 //$this->message('build '.$service['name']);
                 echo $service['org_name'] . ' ';
                 $this->process($command, ['print' => false]);
             }
         }
         echo PHP_EOL;
     }
     if ($checkBuild) {
         echo \Peanut\Console\Color::text('build   | ', 'white');
         foreach ($compose['services'] as $serviceName => $service) {
             if (true === isset($service['build'])) {
                 $buildOpts = [];
                 $buildOpts[] = 'docker';
                 $buildOpts[] = 'build';
                 $buildOpts[] = '--tag=' . $service['name'];
                 if (true === is_array($service['build'])) {
                     if (true === isset($service['build']['args'])) {
                         foreach ($service['build']['args'] as $argKey => $argValue) {
                             $buildOpts[] = '--build-arg ' . $argKey . '=' . escapeshellarg($argValue);
                         }
                     }
                     if (true === isset($service['build']['context'])) {
                         $buildOpts[] = $service['build']['context'];
                     } else {
                         throw new \Console\Exception('build context not found');
                     }
                 } else {
                     $buildOpts[] = $service['build'];
                 }
                 //$this->message('build '.$service['name']);
                 echo $service['org_name'] . ' ';
                 $this->process($buildOpts, ['print' => true]);
             }
         }
         echo PHP_EOL;
     }
     echo \Peanut\Console\Color::text('remove  | ', 'white');
     foreach ($compose['services'] as $serviceName => $service) {
         echo $service['org_name'] . ' ';
         $rmCommand = ['docker', 'rm', '-f', $service['name'], '2>&1'];
         $this->process($rmCommand, ['print' => false]);
     }
     echo PHP_EOL;
     if (true === isset($compose['networks'])) {
     } else {
         // default network setting
         $compose['networks'] = ['default' => ['ipam' => ['config' => [['subnet']]]]];
     }
     if (true === isset($compose['networks'])) {
         $defaultName = $projectName;
         foreach ($compose['networks'] as $networkName => $network) {
             $dockerNetworks = $this->getNetworkList();
             if ('default' == $networkName) {
                 $networkName = 'default[' . $defaultName . ']';
             }
             //$this->networkName[] = $networkName; // --net 은 배열이 아니다.
             $this->networkName = [$networkName];
             if (true === isset($dockerNetworks[$networkName])) {
                 $networkRmcommand = ['docker', 'network', 'rm', $networkName, '2>&1'];
                 $this->process($networkRmcommand, ['print' => false]);
                 unset($dockerNetworks[$networkName]);
             }
             foreach ($dockerNetworks as $dockerNetworkName => $dockerNetworkSubnet) {
                 foreach ($network['ipam']['config'] as $configSubnet) {
                     if (true === isset($configSubnet['subnet']) && $configSubnet['subnet'] == $dockerNetworkSubnet) {
                         $this->message(\Peanut\Console\Color::text($networkName . ' conflicts with network ' . $dockerNetworkName . ', subnet ' . $dockerNetworkSubnet, 'red'));
                         echo 'delete? [y/N]: ';
                         $handle = fopen('php://stdin', 'r');
                         $line = fgets($handle);
                         fclose($handle);
                         if (false === in_array(trim($line), ['y', 'Y'])) {
                             throw new \Peanut\Console\Exception($networkName . ' conflicts with network ' . $dockerNetworkName . ', subnet ' . $dockerNetworkSubnet);
                         } else {
                             $networkRmCommand = ['docker', 'network', 'rm', $dockerNetworkName];
                             $this->process($networkRmCommand, ['print' => false]);
                         }
                     }
                 }
             }
             $subnet = [];
             foreach ($network['ipam']['config'] as $configSubnet) {
                 if (true === isset($configSubnet['subnet']) && $configSubnet['subnet']) {
                     $subnet[] = $configSubnet['subnet'];
                 }
             }
             $networkCreateCommand = ['docker', 'network', 'create', '--driver=bridge'];
             if ($subnet) {
                 $networkCreateCommand[] = '--subnet=' . implode(' --subnet=', $subnet);
             } else {
                 $subnetFile = $this->process('echo $HOME', ['print' => false])->toString() . '/.docker/docker-machine-subnet.yaml';
                 if (false === is_file($subnetFile)) {
                     $this->process('touch ' . $subnetFile, ['print' => false]);
                 }
                 $subnets = \App\Helpers\Yaml::parseFile($subnetFile);
                 if (false === is_array($subnets)) {
                     $subnets = [];
                 }
                 if (true === isset($subnets[$machineName][$projectName])) {
                     $subnet = $subnets[$machineName][$projectName];
                 } else {
                     $bridge = $this->process("docker network inspect --format='{{range .IPAM.Config}}{{.Subnet}}{{end}}' bridge", ['print' => false])->toString();
                     $subnetIps = [];
                     foreach ($subnets as $machines) {
                         if (true === is_array($machines)) {
                             foreach ($machines as $projectIp) {
                                 $subnetIps[] = $projectIp;
                             }
                         }
                     }
                     while (1) {
                         $subnet = '172.' . rand(0, 255) . '.0.0/16';
                         if ($subnet == $bridge) {
                             continue;
                         }
                         if (false == in_array($subnet, $subnetIps)) {
                             break;
                         }
                     }
                     $subnets[$machineName][$projectName] = $subnet;
                     \App\Helpers\Yaml::dumpFile($subnetFile, $subnets);
                 }
                 $networkCreateCommand[] = '--subnet=' . $subnet;
             }
             $networkCreateCommand[] = $networkName;
             $networkCreateCommand[] = '2>&1';
             $this->process($networkCreateCommand, ['print' => false]);
             $networkInspectCommand = ['docker', 'network', 'inspect', '--format="{{range .IPAM.Config}}{{.Subnet}}{{end}}"', $networkName, '2>&1'];
             $subnet = $this->process($networkInspectCommand, ['print' => false])->toArray();
             if (!$subnet) {
                 throw new \Peanut\Console\Exception('network ' . $networkName . ' not found');
             }
             echo \Peanut\Console\Color::text('network | ', 'white') . 'recreate ' . $networkName . ', subnet ' . implode(' ', $subnet) . PHP_EOL;
         }
     }
     if ('attach' == $mode) {
         echo \Peanut\Console\Color::text('create  | ', 'white');
     } else {
         echo \Peanut\Console\Color::text('run     | ', 'white');
     }
     $runCommands = [];
     foreach ($compose['services'] as $serviceName => $service) {
         $command = [];
         if ('attach' == $mode) {
             $command[] = 'docker create';
             $command[] = '-a STDIN';
             $command[] = '-a STDOUT';
             $command[] = '-a STDERR';
             $command[] = '-i';
         } else {
             $command[] = 'docker run';
             $command[] = '-d';
             $command[] = '-i';
             if (true === isset($service['tty'])) {
                 $command[] = '--tty';
             }
         }
         if (true === isset($service['privileged'])) {
             $command[] = '--privileged';
         }
         if ($this->networkName) {
             foreach ($this->networkName as $networkName) {
                 $command[] = '--net=' . $networkName;
             }
         }
         if (true === isset($service['networks'])) {
             foreach ($service['networks'] as $name => $conf) {
                 if (true === isset($conf['ipv4_address'])) {
                     $command[] = '--ip=' . $conf['ipv4_address'];
                 }
                 if (true === isset($conf['ipv6_address'])) {
                     $command[] = '--ip6=' . $conf['ipv6_address'];
                 }
             }
         }
         if (true === isset($service['dns'])) {
             foreach ($service['dns'] as $value) {
                 $command[] = '--dns=' . $value;
             }
         }
         if (true === isset($service['env-file'])) {
             foreach ($service['env-file'] as $value) {
                 $command[] = '--env-file=' . $value;
             }
         }
         $command[] = '-e TERM=xterm';
         if (true === isset($service['environment'])) {
             foreach ($service['environment'] as $key => $value) {
                 if (true === is_array($value)) {
                     $value = "'" . json_encode($value, JSON_UNESCAPED_SLASHES) . "'";
                 }
                 $command[] = '-e ' . $key . '=' . escapeshellarg($value);
             }
         }
         if (true === isset($service['expose'])) {
             foreach ($service['expose'] as $key => $value) {
                 $command[] = '--expose=' . $value;
             }
         }
         if (true === isset($service['user'])) {
             $command[] = '--user='******'user'];
         }
         if (true === isset($service['hostname'])) {
             $command[] = '--hostname=' . $service['hostname'];
         }
         $addHost = [];
         if (true === isset($service['links'])) {
             foreach ($service['links'] as $key => $value) {
                 foreach ($this->networkName as $networkName) {
                     $inspectCommand = ['docker', 'inspect', '--format="service={{index .Config.Labels \\"com.docker.bootapp.service\\"}}&&ip={{with index .NetworkSettings.Networks \\"' . $networkName . '\\"}}{{.IPAddress}}{{end}}"', $this->getContainerName($value)];
                     $str = $this->process($inspectCommand, ['print' => false])->toString();
                     parse_str($str, $out);
                     if (true === isset($out['ip']) && true === isset($out['service'])) {
                         $ip = $out['ip'];
                         $serviceName = $out['service'];
                         $addHost[$ip] = $serviceName . ' ' . $this->getContainerName($value);
                     }
                 }
                 $command[] = '--link=' . $this->getContainerName($value);
             }
         }
         foreach ($addHost as $ip => $host) {
             $command[] = '--add-host="' . $host . '":' . $ip;
         }
         if (true === isset($service['net'])) {
             $command[] = '--net=' . $service['net'];
         }
         if (true === isset($service['working_dir'])) {
             $command[] = '--workdir=' . $service['working_dir'];
         }
         if (true === isset($service['ports'])) {
             foreach ($service['ports'] as $value) {
                 $command[] = '--publish=' . $value;
             }
         } else {
             //$command[] = '-P';
         }
         if (true === isset($service['restart'])) {
             $command[] = '--restart=' . $service['restart'];
         }
         if (true === isset($service['volumes'])) {
             foreach ($service['volumes'] as $value) {
                 $command[] = '-v ' . $this->volumeRealPath($value);
             }
         }
         if (true === isset($service['volumes_from'])) {
             foreach ($service['volumes_from'] as $value) {
                 $command[] = '--volumes-from=' . ($projectName ? $projectName . '-' . $value : $value);
             }
         }
         if (true === isset($service['entrypoint'])) {
             $command[] = '--entrypoint=' . $service['entrypoint'];
         }
         $command[] = '--name=' . $service['name'];
         if (true === isset($service['labels'])) {
             foreach ($service['labels'] as $labelName => $labelValue) {
                 $command[] = '--label ' . $labelName . '="' . $labelValue . '"';
             }
         }
         if (true === isset($service['environment']['DOMAIN'])) {
             if (false === strpos($service['environment']['DOMAIN'], ' ')) {
                 $command[] = '--label com.docker.bootapp.domain="' . $service['environment']['DOMAIN'] . '"';
             } else {
                 throw new \Peanut\Console\Exception('domain name not valid');
             }
         }
         if (true === isset($service['image'])) {
             $command[] = $service['image'];
         }
         if (true === isset($service['build'])) {
             $command[] = $service['name'];
         }
         if (true === isset($service['command'])) {
             $command[] = $service['command'];
         }
         $runCommands[] = implode(' ', $command);
         $this->process($command, ['print' => false]);
         // create
         echo $service['org_name'] . ' ';
     }
     echo PHP_EOL;
     if ('attach' == $mode) {
         echo \Peanut\Console\Color::text('start   | ', 'white');
         foreach ($compose['services'] as $serviceName => $service) {
             echo $service['org_name'] . ' ';
             $command = ['docker', 'start', $service['name']];
             $this->process($command, ['print' => false]);
         }
         echo PHP_EOL;
         echo 'attach  | ';
         foreach ($compose['services'] as $serviceName => $service) {
             echo $service['org_name'] . ' ';
             $command = ['docker', 'logs', $service['name'], '&&', 'docker', 'attach', '--sig-proxy=true', $service['name']];
             $this->childProcess($service['name'], implode(' ', $command));
         }
         echo PHP_EOL;
     } else {
     }
 }