diff --git a/README.md b/README.md index b211119..04ce29f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ up a ready-to-roll mongodb or openldap server, it does what it is supposed to. ## Todo -- [ ] Add a --temporary option to start to remove volume after stop - [x] Rename from `serverctl` to `server` - [x] Implement variables in environment section - [x] Provide environment, ex. `${SERVER_HOST}` for docker host IP @@ -16,6 +15,7 @@ up a ready-to-roll mongodb or openldap server, it does what it is supposed to. - [ ] App port binding, i.e. phpmyadmin on 9000, phpcacheadmin on 9001 - [ ] Make use of a `~/.serverenvs` to override envs for instances - [x] Consider UDP? +- [ ] Fix the service scripts implementation ## Examples @@ -86,12 +86,26 @@ the project root when running from source. } ``` +## Permanently customizing instances + +To customize an instance, create the file `~/.serverenvs` if it doesn't exist +and open in a text editor. The definitions for each instance is contained in +a section named after the server and the instance name separated by a colon: + +``` +[mysql:backups] +MYSQL_ROOT_PASSWORD=something + +[server:instance] +ENV_VAR=value +``` ## FAQ ### Where is the data stored? -* Data goes in `$HOME/.var/serverctl` +Data goes in `$HOME/.var/serverctl`. As volumes are generally not owned by your +user, you will have to manually delete old instances. ### How can I tell a container to connect to another container? diff --git a/src/Container/ContainerManager.php b/src/Container/ContainerManager.php index 378ac7d..341c639 100644 --- a/src/Container/ContainerManager.php +++ b/src/Container/ContainerManager.php @@ -13,11 +13,28 @@ class ContainerManager private array $autoEnv = []; + private array $serverEnvs = []; + public function __construct(?string $dataPath=null) { $this->dataPath = $dataPath ?? (getenv("HOME")."/.var/serverctl"); $this->stateFile = $this->dataPath . "/state.json"; $this->setupAutoEnv(); + $this->setupServerEnvs(); + } + + private function setupServerEnvs() + { + $file = getenv("HOME")."/.serverenvs"; + + if (!file_exists($file)) { + $this->serverEnvs = []; + return; + } + + $parsed = parse_ini_file($file, true); + + $this->serverEnvs = $parsed; } private function setupAutoEnv() @@ -105,6 +122,11 @@ class ContainerManager $instanceName = $options['name']??'default'; $portOffset = intval($options['portoffset']??0); + $temporary = $option['temporary']??false; + if ($temporary) { + $instanceName = sprintf("%04x%04x", rand(0,0xFFFF), rand(0,0xFFFF)); + } + $containerName = "sm_".$serviceName."_".$instanceName; $args[] = 'run'; @@ -136,10 +158,22 @@ class ContainerManager $args[] = $volumePath."/".$hint.":".$path; } + $parsedEnv = []; + + // Prepared environment from serviceenvs + $key = $serviceName . ":" . $instanceName; + if (array_key_exists($key, $this->serverEnvs)) { + foreach ($this->serverEnvs[$key] as $env=>$value) { + $value = $this->expandString($value); + array_push($args, "-e", sprintf("%s=%s", $env, $value)); + $parsedEnv[$env] = $value; + } + } + // Get environment $envs = (array)($service['environment']??[]); - $parsedEnv = []; foreach ($envs as $env=>$value) { + if (array_key_exists($env, $parsedEnv)) continue; $args[] = '-e'; $envval = getenv($env, true); if ($envval) $value = $envval; @@ -153,6 +187,7 @@ class ContainerManager $cmdl = 'docker '.join(' ',array_map('escapeshellarg', $args)); //echo "$ {$cmdl}\n"; + exec($cmdl, $out, $ret); if ($ret != 0) { echo join("\n",$out)."\n"; @@ -164,7 +199,8 @@ class ContainerManager 'instance' => $instanceName, 'environment' => $parsedEnv, 'service' => $service, - 'ports' => $mappedPorts + 'ports' => $mappedPorts, + 'temporary' => $temporary, ]); return [