10000 Docker support (Docker Compose and Dockerfile) · symfony/flex@78c2bec · GitHub
[go: up one dir, main page]

Skip to content

Commit 78c2bec

Browse files
committed
Docker support (Docker Compose and Dockerfile)
1 parent cc58019 commit 78c2bec

File tree

5 files changed

+708
-0
lines changed

5 files changed

+708
-0
lines changed

src/Configurator.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ public function __construct(Composer $composer, IOInterface $io, Options $option
4141
'makefile' => Configurator\MakefileConfigurator::class,
4242
'composer-scripts' => Configurator\ComposerScriptsConfigurator::class,
4343
'gitignore' => Configurator\GitignoreConfigurator::class,
44+
'dockerfile' => Configurator\DockerfileConfigurator::class,
45+
'docker-compose' => Configurator\DockerComposeConfigurator::class,
4446
];
4547
}
4648

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Flex\Configurator;
13+
14+
use Symfony\Flex\Lock;
15+
use Symfony\Flex\Recipe;
16+
17+
/**
18+
* Adds services and volumes to docker-compose.yml file.
19+
*
20+
* @author Kévin Dunglas <dunglas@gmail.com>
21+
*/
22+
class DockerComposeConfigurator extends AbstractConfigurator
23+
{
24+
public function configure(Recipe $recipe, $config, Lock $lock, array $options = [])
25+
{
26+
$installDocker = $this->composer->getPackage()->getExtra()['symfony']['docker'] ?? false;
27+
if (!$installDocker) {
28+
return;
29+
}
30+
31+
$rootDir = $this->options->get('root-dir');
32+
if (
33+
(
34+
!file_exists($dockerComposeFile = $rootDir.'/docker-compose.yml') &&
35+
!file_exists($dockerComposeFile = $rootDir.'/docker-compose.yaml')
36+
) || $this->isFileMarked($recipe, $dockerComposeFile)
37+
) {
38+
return;
39+
}
40+
41+
$this->write('Adding Docker Compose entries');
42+
43+
$offset = 8;
44+
$node = null;
45+
$endAt = [];
46+
$lines = [];
47+
foreach (file($dockerComposeFile) as $i => $line) {
48+
$lines[] = $line;
49+
$ltrimedLine = ltrim($line, ' ');
50+
51+
// Skip blank lines and comments
52+
if (('' !== $ltrimedLine && 0 === strpos($ltrimedLine, '#')) || '' === trim($line)) {
53+
continue;
54+
}
55+
56+
// Extract Docker Compose keys (usually "services" and "volumes")
57+
if (!preg_match('/^[\'"]?([a-zA-Z0-9]+)[\'"]?:\s*$/', $line, $matches)) {
58+
// Detect indentation to use
59+
$offestLine = \strlen($line) - \strlen($ltrimedLine);
60+
if ($offset > $offestLine && 0 !== $offestLine) {
61+
$offset = $offestLine;
62+
}
63+
continue;
64+
}
65+
66+
// Keep end in memory (check break line on previous line)
67+
$endAt[$node] = '' !== trim($lines[$i - 1]) ? $i : $i - 1;
68+
$node = $matches[1];
69+
}
70+
$endAt[$node] = \count($lines) + 1;
71+
72+
foreach ($config as $key => $value) {
73+
if (isset($endAt[$key])) {
74+
array_splice($lines, $endAt[$key], 0, $this->markData($recipe, $this->parse(1, $offset, $value)));
75+
continue;
76+
}
77+
78+
$lines[] = sprintf("\n%s:", $key);
79+
$lines[] = $this->markData($recipe, $this->parse(1, $offset, $value));
80+
}
81+
82+
file_put_contents($dockerComposeFile, implode('', $lines));
83+
}
84+
85+
public function unconfigure(Recipe $recipe, $config, Lock $lock)
86+
{
87+
$rootDir = $this->options->get('root-dir');
88+
if (!file_exists($dockerCompose = $rootDir.'/docker-compose.yml') &&
89+
!file_exists($dockerCompose = $rootDir.'/docker-compose.yaml')
90+
) {
91+
return;
92+
}
93+
94+
$name = $recipe->getName();
95+
// Remove recipe and add break line
96+
$contents = preg_replace(sprintf('{%s+###> %s ###.*?###< %s ###%s+}s', "\n", $name, $name, "\n"), PHP_EOL.PHP_EOL, file_get_contents($dockerCompose), -1, $count);
97+
if (!$count) {
98+
return;
99+
}
100+
101+
foreach ($config as $key => $value) {
102+
if (0 === preg_match(sprintf('{^%s:[ \t\r\n]*([ \t]+\w)}m', $key), $contents, $matches)) {
103+
$contents = preg_replace(sprintf('{\n?^%s:[ \t\r\n]*}sm', $key), '', $contents, -1, $count);
104+
}
105+
}
106+
107+
$this->write(sprintf('Removing Docker Compose entries from %s', $dockerCompose));
108+
file_put_contents($dockerCompose, ltrim($contents, "\n"));
109+
}
110+
111+
private function parse($level, $indent, $services): string
112+
{
113+
$line = '';
114+
foreach ($services as $key => $value) {
115+
$line .= str_repeat(' ', $indent * $level);
116+
if (!\is_array($value)) {
117+
if (\is_string($key)) {
118+
$line .= sprintf('%s:', $key);
119+
}
120+
$line .= sprintf("%s\n", $value);
121+
continue;
122+
}
123+
$line .= sprintf("%s:\n", $key).$this->parse($level + 1, $indent, $value);
124+
}
125+
126+
return $line;
127+
}
128+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Flex\Configurator;
13+
14+
use Symfony\Flex\Lock;
15+
use Symfony\Flex\Recipe;
16+
17+
/**
18+
* Adds commands to a Dockerfile.
19+
*
20+
* @author Kévin Dunglas <dunglas@gmail.com>
21+
*/
22+
class DockerfileConfigurator extends AbstractConfigurator
23+ 10000
{
24+
public function configure(Recipe $recipe, $config, Lock $lock, array $options = [])
25+
{
26+
$installDocker = $this->composer->getPackage()->getExtra()['symfony']['docker'] ?? false;
27+
if (!$installDocker) {
28+
return;
29+
}
30+
31+
$dockerfile = $this->options->get('root-dir').'/Dockerfile';
32+
if (!file_exists($dockerfile) || $this->isFileMarked($recipe, $dockerfile)) {
33+
return;
34+
}
35+
36+
$this->write('Adding Dockerfile entries');
37+
38+
$lines = [];
39+
foreach (file($dockerfile) as $line) {
40+
$lines[] = $line;
41+
if (!preg_match('/^###> recipes ###$/', $line)) {
42+
continue;
43+
}
44+
45+
$lines[] = ltrim($this->markData($recipe, implode("\n", $config)), "\n");
46+
}
47+
48+
file_put_contents($dockerfile, implode('', $lines));
49+
}
50+
51+
public function unconfigure(Recipe $recipe, $config, Lock $lock)
52+
{
53+
if (!file_exists($dockerfile = $this->options->get('root-dir').'/Dockerfile')) {
54+
return;
55+
}
56+
57+
$name = $recipe->getName();
58+
$contents = preg_replace(sprintf('{%s+###> %s ###.*?###< %s ###%s+}s', "\n", $name, $name, "\n"), "\n", file_get_contents($dockerfile), -1, $count);
59+
if (!$count) {
60+
return;
61+
}
62+
63+
$this->write('Removing Dockerfile entries');
64+
file_put_contents($dockerfile, ltrim($contents, "\n"));
65+
}
66+
}

0 commit comments

Comments
 (0)
0