Skip to content

Commit a8d2d09

Browse files
Merge pull request #4 from idrislab/develop
Develop
2 parents f2d3e31 + fe4e1a4 commit a8d2d09

File tree

2 files changed

+161
-93
lines changed

2 files changed

+161
-93
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"email": "luis@idris.pt"
88
}
99
],
10-
"keywords": ["laravel", "docker", "services"],
10+
"keywords": ["laravel", "docker", "containers", "automate"],
1111
"license": "MIT",
1212
"require": {
1313
"php": ">=5.6.4",

src/DockerContainers.php

Lines changed: 160 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,22 @@ class DockerContainers extends Command
6565
* @var Docker
6666
*/
6767
protected $docker;
68+
/**
69+
* @var array
70+
*/
71+
protected $attributes;
72+
/**
73+
* @var array
74+
*/
6875
protected $network = [];
76+
/**
77+
* @var array
78+
*/
79+
protected $instances;
80+
/**
81+
* @var array
82+
*/
83+
protected $container;
6984

7085
/**
7186
* Create a new command instance.
@@ -92,27 +107,37 @@ public function handle()
92107
collect(explode(",", $containers))
93108
->mapWithKeys(function ($container) {
94109
//Retrieve only current container attributes
95-
$containers = collect($this->containers)->map(function ($attributes, $current) use (&$container) {
96-
if (strtolower($current) === strtolower($container)) {
97-
$container = $current;
98-
99-
return $attributes;
100-
}
101-
})->only($container);
110+
$containers = collect($this->containers)
111+
->map(function ($attributes, $current) use (&$container) {
112+
if ($this->option('name') === null) {
113+
if (strtolower($current) === strtolower($container)) {
114+
$container = $current;
115+
116+
return $attributes;
117+
}
118+
} elseif (strtolower($this->option('name')) === strtolower($current)) {
119+
$container = $current;
120+
121+
return $attributes;
122+
}
123+
})
124+
->only($container);
102125

103126
return $containers;
104127
})
105128
->each(function ($attributes, $container) {
106129

130+
$this->prepare($container, $attributes);
131+
107132
switch ($this->argument('option')) {
108133
case "start":
109-
$this->startContainer($container, $attributes);
134+
$this->start();
110135
break;
111136
case 'stop':
112-
return $this->stopContainer($container, $attributes);
137+
return $this->stop();
113138
break;
114139
case 'restart':
115-
$this->restartContainer($container, $attributes);
140+
$this->restart();
116141
break;
117142
default:
118143
}
@@ -122,6 +147,8 @@ public function handle()
122147
}
123148

124149
/**
150+
* Add containers
151+
*
125152
* @param array $containers
126153
*/
127154
protected function addContainers(array $containers)
@@ -130,116 +157,81 @@ protected function addContainers(array $containers)
130157
}
131158

132159
/**
133-
* @param string $container
134-
* @param array $attributes
160+
* Start docker container
135161
*/
136-
private function startContainer($container, array $attributes)
162+
private function start()
137163
{
138-
$tag = $attributes['repo'].':'.$attributes['tag'];
139-
if (!$this->docker->imageExists($tag)) {
140-
$this->docker->pull($tag);
141-
}
164+
$this->pullImage();
142165

143-
$instances = $this->getContainerInstances($container, $attributes);
166+
foreach ($this->instances as $container) {
167+
$this->container = $container;
144168

145-
foreach ($instances as $instance) {
146-
if ($this->docker->isNamedContainerRunning($instance['name'])) {
147-
if (!$this->confirm("$container is already running, do you want restart?")) {
148-
continue;
169+
if ($this->docker->isNamedContainerRunning($container['name'])) {
170+
if ($this->confirm("{$container['name']} is already running, do you want restart?")) {
171+
$this->restart();
149172
}
150-
151-
$this->restartContainer($instance, $attributes);
152-
break;
173+
continue;
153174
}
154175

155-
$this->runContainer($instance, $attributes);
176+
$this->runContainer();
156177
}
157178
}
158179

159180
/**
160-
* @param array $container
161-
* @param array $attributes
162-
*
163-
* @throws Exception
181+
* Run docker container
164182
*/
165-
private function runContainer(array $container, array $attributes)
183+
private function runContainer()
166184
{
167-
$name = $container['name'];
168-
$instance = $container['instance'];
169-
170-
putenv('INSTANCE_NAME='.$instance);
171-
172-
$this->info("Starting {$container['service']} $instance", false);
173-
174-
if (isset($attributes['command'])) {
175-
$command = $attributes['command'];
176-
} else {
177-
if (isset($attributes['commands'])) {
178-
$command = $attributes['commands'][$instance];
179-
} else {
180-
throw new Exception("Container {$container['service']} command or commands must be set");
181-
}
182-
}
185+
putenv('CURRENT_INSTANCE='.$this->container['instance']);
183186

184-
if (isset($attributes['docker']['pre'])) {
185-
foreach ($attributes['docker']['pre'] as $command) {
186-
$this->docker->docker($command);
187-
}
188-
}
189-
190-
$command = '--name '.$name." ".$this->parseDotEnvVars($command);
191-
$this->docker->run($command);
187+
$this->info("Starting {$this->container['service']} #{$this->container['instance']}", false);
192188

193-
$network = isset($attributes['network']) ? $attributes['network'] : 'bridge';
194-
$this->network[] = $this->getContainerNetwork($container, $network);
189+
$this->preCommand();
190+
$this->runCommand($this->getContainerCommand());
191+
$this->postCommand();
195192

196-
if (isset($attributes['docker']['post'])) {
197-
foreach ($attributes['docker']['post'] as $command) {
198-
$this->docker->docker($command);
199-
}
200-
}
193+
$this->setContainerNetwork();
201194
}
202195

203196
/**
204-
* @param string $container
205-
* @param array $attributes
197+
* Stop docker container
206198
*/
207-
private function stopContainer($container, array $attributes)
199+
private function stop()
208200
{
209-
if ($this->option('service') != "") {
210-
if (strtolower($this->option('service')) != strtolower($container)) {
201+
collect($this->instances)->each(function ($container) {
202+
$this->info("Stopping {$container['service']} #{$container['instance']}");
203+
204+
if (!$this->docker->isNamedContainerRunning($container['name'])) {
205+
if ($this->confirm("{$container['service']} is not running, do you want start?")) {
206+
$this->start();
207+
}
208+
211209
return;
212210
}
213-
}
214211

215-
$containers = $this->getContainers($container, $attributes);
216-
217-
collect($containers)->each(function ($container) use ($container) {
218-
$this->info("Stopping $container ".$container['instance']);
219212
$this->docker->stopNamedContainer($container['name']);
220213
$this->docker->removeNamedContainer($container['name']);
221214
});
222215
}
223216

224-
225217
/**
226-
* @param string $container
227-
* @param array $attributes
218+
* Restart docker containers
228219
*/
229-
private function restartContainer($container, array $attributes)
220+
private function restart()
230221
{
231-
$this->info('Restarting '.$container);
232-
$this->stopContainer($container, $attributes);
233-
$this->startContainer($container, $attributes);
222+
$this->stop();
223+
$this->start();
234224
}
235225

236226
/**
227+
* Prepare environment
228+
*
237229
* @param string $container
238230
* @param array $attributes
239231
*
240232
* @return array
241233
*/
242-
private function getContainerInstances($container, array $attributes)
234+
private function prepare($container, array $attributes)
243235
{
244236
$name = strtolower('laravel-'.$container);
245237
$instances = isset($attributes['instances']) ? (int)$attributes['instances'] : 1;
@@ -252,16 +244,19 @@ private function getContainerInstances($container, array $attributes)
252244
putenv($envVar);
253245
}
254246

255-
return $containers;
247+
$this->instances = $containers;
248+
$this->attributes = $attributes;
256249
}
257250

258251
/**
252+
* Parse environment variables
253+
*
259254
* @param $string
260255
*
261256
* @throws Exception
262257
* @return string
263258
*/
264-
public function parseDotEnvVars($string)
259+
public function parseEnvVars($string)
265260
{
266261
$found = preg_match_all('/((.*?)ENV\[([^|]+?)(\|(.+))?\](.*?))/', $string, $matches);
267262

@@ -282,30 +277,103 @@ public function parseDotEnvVars($string)
282277
}
283278

284279
/**
285-
* @param array $container
286-
* @param string $network
280+
* Set container network information
287281
*
288282
* @return array
289283
*/
290-
private function getContainerNetwork($container, $network)
284+
private function setContainerNetwork()
291285
{
292-
$host = $this->docker->getNamedContainerIp($container['name'], $network);
293-
$port = $this->docker->getNamedContainerPorts($container['name']);
286+
$network = isset($this->attributes['network']) ? $this->attributes['network'] : 'bridge';
294287

295-
return [
296-
'service' => ucfirst($container['service']),
297-
'host' => $host,
298-
'port' => implode(", ", $port),
288+
$host = $this->docker->getNamedContainerIp($this->container['name'], $network);
289+
$port = $this->docker->getNamedContainerPorts($this->container['name']);
290+
291+
$this->network[] = [
292+
'container' => ucfirst($this->container['service']).' #'.$this->container['instance'],
293+
'host' => $host,
294+
'port' => implode(", ", $port),
299295
];
300296
}
301297

298+
/**
299+
* Render a console table displaying network information
300+
* for each docker container running
301+
*/
302302
private function renderNetworkTable()
303303
{
304304
if (empty($this->network)) {
305305
return;
306306
}
307307

308-
$headers = ['Service', ' Host', 'Port'];
308+
$headers = ['Container', 'Host', 'Port'];
309309
$this->table($headers, $this->network);
310310
}
311+
312+
/**
313+
* Pull image from docker hub
314+
*/
315+
private function pullImage()
316+
{
317+
$tag = $this->attributes['repo'].':'.$this->attributes['tag'];
318+
if (!$this->docker->imageExists($tag)) {
319+
$this->docker->pull($tag);
320+
}
321+
}
322+
323+
/**
324+
* Get normalized docker run command
325+
*
326+
* @return string
327+
* @throws \Exception
328+
*/
329+
private function getContainerCommand()
330+
{
331+
$attributes = $this->attributes;
332+
333+
if (isset($attributes['command'])) {
334+
$command = $attributes['command'];
335+
} else {
336+
if (isset($attributes['commands'])) {
337+
$command = $attributes['commands'][$this->container['instance']];
338+
} else {
339+
throw new Exception("Container {$this->container['service']} command or commands must be set");
340+
}
341+
}
342+
343+
return '--name '.$this->container['name'].' '.$this->parseEnvVars($command);
344+
}
345+
346+
/**
347+
* Run pre execution commands
348+
*/
349+
private function preCommand()
350+
{
351+
if (isset($attributes['docker']['pre'])) {
352+
foreach ($attributes['docker']['pre'] as $command) {
353+
$this->docker->docker($this->parseEnvVars($command));
354+
}
355+
}
356+
}
357+
358+
/**
359+
* Run post execution commands
360+
*/
361+
private function postCommand()
362+
{
363+
if (isset($attributes['docker']['post'])) {
364+
foreach ($attributes['docker']['post'] as $command) {
365+
$this->docker->docker($this->parseEnvVars($command));
366+
}
367+
}
368+
}
369+
370+
/**
371+
* Perform docker run
372+
*
373+
* @param string $command
374+
*/
375+
private function runCommand($command)
376+
{
377+
$this->docker->run($command);
378+
}
311379
}

0 commit comments

Comments
 (0)