Compare commits

..

2 commits

Author SHA1 Message Date
Daniel Winning
acf87efdb9 Nginx setup 2025-04-13 20:07:48 +01:00
Daniel Winning
f276d19bc8 Fix setting PHP version in .env 2025-04-13 13:35:39 +01:00
13 changed files with 173 additions and 26 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
/.idea
/vendor
composer.lock
/public/*

View file

@ -1,6 +1,10 @@
# Project Settings
PROJECT_DIRECTORY=%s
PROJECT_NAME=%s
PHP_VERSION=%s
# Ports
# PHP
PHP_VERSION=%s
PHP_PORT=%s
# Nginx
NGINX_PORT=%s

9
config/nginx.yaml Normal file
View file

@ -0,0 +1,9 @@
services:
nginx:
build:
context: ./nginx
ports:
- ${NGINX_PORT}:80
volumes:
- ${PROJECT_DIRECTORY}:/var/www/html:cached
- ./nginx/conf.d:/etc/nginx/conf.d

5
config/nginx/Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM nginx:1.23-alpine
CMD ["nginx", "-g", "daemon off;"]
EXPOSE 80 443

View file

@ -0,0 +1,25 @@
server {
listen 80;
listen [::]:80;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
index index.php index.html;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
location ~ \.php$ {
try_files $uri = 404;
fastcgi_split_path_info ^(.+`.php)(/.+)$;
fastcgi_pass php:9000;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}

View file

@ -4,4 +4,6 @@ options:
version: 8.4
node:
enabled: true
version: 20
version: 23
server:
enabled: true

View file

@ -52,13 +52,25 @@ class Config
*/
public function isNodeEnabled(InputInterface $input): bool
{
if ($input->getOption('node-disabled')) {
if ($input->getOption('disable-node')) {
return false;
}
return $this->getEnvironmentOption('node', 'enabled');
}
/**
* @throws \Exception
*/
public function isServerEnabled(InputInterface $input): bool
{
if ($input->getOption('disable-server')) {
return false;
}
return $this->getEnvironmentOption('server', 'enabled');
}
/**
* @throws \Exception
*/
@ -109,8 +121,10 @@ class Config
'envTemplate' => new SpinnerFilePath('config/.template.env'),
'data' => new SpinnerFilePath('data'),
'phpYamlTemplate' => new SpinnerFilePath('config/php.yaml'),
'nginxYamlTemplate' => new SpinnerFilePath('config/nginx.yaml'),
'phpFpmDataDirectory' => new SpinnerFilePath('config/php-fpm'),
DataPathInterface::CONFIG_PHP_FPM_DIRECTORY => new SpinnerFilePath(DataPathInterface::CONFIG_PHP_FPM_DIRECTORY),
DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE => new SpinnerFilePath(DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE),
DataPathInterface::CONFIG_NGINX_DOCKERFILE => new SpinnerFilePath(DataPathInterface::CONFIG_NGINX_DOCKERFILE),
'nodeDockerfileTemplate' => new SpinnerFilePath('config/php-fpm/Node.Dockerfile'),
]);
}

View file

@ -14,7 +14,7 @@ class DockerComposeFileBuilder extends AbstractFileBuilder
*/
public function __construct(Config $config)
{
$projectDockerCompose = $this->config->getFilePaths()->get('projectDockerCompose');
$projectDockerCompose = $config->getFilePaths()->get('projectDockerCompose');
if (!$projectDockerCompose instanceof SpinnerFilePath) {
throw new \Exception('Project Docker Compose file path not found.');
@ -23,12 +23,35 @@ class DockerComposeFileBuilder extends AbstractFileBuilder
return parent::__construct($projectDockerCompose, $config);
}
/**
* @throws \Exception
*/
public function build(InputInterface $input): DockerComposeFileBuilder
{
$this->content = file_get_contents(
$this->config->getFilePaths()->get('phpYamlTemplate')->getAbsolutePath()
);
if ($this->config->isServerEnabled($input)) {
$this->addNginxConfig();
}
return $this;
}
private function addNginxConfig(): void
{
$this->content .= str_replace(
'services:',
'',
file_get_contents(
$this->config->getFilePaths()->get('nginxYamlTemplate')->getAbsolutePath()
)
);
$this->content = str_replace(
'./nginx/conf.d',
(new SpinnerFilePath('config/nginx/conf.d'))->getAbsolutePath(),
$this->content
);
}
}

View file

@ -6,5 +6,6 @@ namespace Loom\Spinner\Classes\File\Interface;
interface DataPathInterface
{
public const string CONFIG_PHP_FPM_DIRECTORY = 'config/php-fpm/Dockerfile';
public const string CONFIG_PHP_FPM_DOCKERFILE = 'config/php-fpm/Dockerfile';
public const string CONFIG_NGINX_DOCKERFILE = 'config/nginx/Dockerfile';
}

View file

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Loom\Spinner\Classes\File;
use Loom\Spinner\Classes\Config\Config;
use Loom\Spinner\Classes\File\Interface\DataPathInterface;
use Symfony\Component\Console\Input\InputInterface;
class NginxDockerFileBuilder extends AbstractFileBuilder
{
/**
* @throws \Exception
*/
public function __construct(Config $config)
{
$projectNginxDockerfilePath = $config->getFilePath('projectNginxDockerfile');
if (!$projectNginxDockerfilePath instanceof SpinnerFilePath) {
throw new \Exception('Project PHP-FPM Dockerfile not found');
}
return parent::__construct($projectNginxDockerfilePath, $config);
}
public function build(InputInterface $input): AbstractFileBuilder
{
$this->content = file_get_contents(
$this->config->getFilePaths()
->get(DataPathInterface::CONFIG_NGINX_DOCKERFILE)
->getAbsolutePath()
);
return $this;
}
}

View file

@ -44,7 +44,7 @@ class PHPDockerFileBuilder extends AbstractFileBuilder
private function setInitialContent(): void
{
$this->content = file_get_contents(
$this->config->getFilePaths()->get(DataPathInterface::CONFIG_PHP_FPM_DIRECTORY)->getAbsolutePath()
$this->config->getFilePaths()->get(DataPathInterface::CONFIG_PHP_FPM_DOCKERFILE)->getAbsolutePath()
);
}
}

View file

@ -94,17 +94,13 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
new SpinnerFilePath(sprintf('data/environments/%s/docker-compose.yml', $input->getArgument('name'))),
'projectDockerCompose'
);
$this->config->addFilePath(
new SpinnerFilePath(sprintf('data/environments/%s/php-fpm', $input->getArgument('name'))),
'projectPhpFpmDirectory'
);
$this->config->addFilePath(
new SpinnerFilePath(sprintf('data/environments/%s/php-fpm/Dockerfile', $input->getArgument('name'))),
'projectPhpFpmDockerfile'
);
$this->config->addFilePath(
new SpinnerFilePath(sprintf('data/environments/%s/php-fpm/Node.Dockerfile', $input->getArgument('name'))),
'projectPhpFpmNodeDockerfile'
new SpinnerFilePath(sprintf('data/environments/%s/nginx/Dockerfile', $input->getArgument('name'))),
'projectNginxDockerfile'
);
$this->config->addFilePath(
new FilePath($this->config->getFilePaths()->get('project')->getAbsolutePath() . DIRECTORY_SEPARATOR . 'spinner.yaml'),

View file

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Loom\Spinner\Command;
use Loom\Spinner\Classes\File\DockerComposeFileBuilder;
use Loom\Spinner\Classes\File\NginxDockerFileBuilder;
use Loom\Spinner\Classes\File\PHPDockerFileBuilder;
use Loom\Spinner\Classes\File\SpinnerFilePath;
use Loom\Spinner\Classes\OS\PortGenerator;
@ -26,6 +27,7 @@ class SpinCommand extends AbstractSpinnerCommand
$this->portGenerator = new PortGenerator();
$this->ports = [
'php' => $this->portGenerator->generateRandomPort(),
'nginx' => $this->portGenerator->generateRandomPort(),
];
parent::__construct();
@ -46,7 +48,13 @@ class SpinCommand extends AbstractSpinnerCommand
'The PHP version to use (e.g., 8.0).'
)
->addOption(
'node-disabled',
'disable-node',
null,
InputOption::VALUE_NONE,
'Set this flag to disable Node.js for your environment.'
)
->addOption(
'disable-server',
null,
InputOption::VALUE_NONE,
'Set this flag to disable Node.js for your environment.'
@ -71,9 +79,9 @@ class SpinCommand extends AbstractSpinnerCommand
$this->style->text('Creating project data...');
$this->createProjectData($input);
// $command = $this->buildDockerComposeCommand(sprintf('-p %s up', $input->getArgument('name')));
//
// passthru($command);
$command = $this->buildDockerComposeCommand(sprintf('-p %s up', $input->getArgument('name')));
passthru($command);
return Command::SUCCESS;
}
@ -97,7 +105,7 @@ class SpinCommand extends AbstractSpinnerCommand
$this->createProjectDataDirectory();
$this->createEnvironmentFile($input);
$this->buildDockerComposeFile($input);
$this->buildDockerfile($input);
$this->buildDockerfiles($input);
}
/**
@ -131,8 +139,9 @@ class SpinCommand extends AbstractSpinnerCommand
file_get_contents($this->config->getFilePaths()->get('envTemplate')->getAbsolutePath()),
$this->config->getFilePaths()->get('project')->getAbsolutePath(),
$input->getArgument('name'),
$input->getOption('php'),
$this->config->getPhpVersion($input),
$this->getPort('php'),
$this->getPort('nginx'),
)
);
}
@ -144,9 +153,22 @@ class SpinCommand extends AbstractSpinnerCommand
{
$this->createProjectPhpFpmDirectory();
if ($this->config->isServerEnabled($input)) {
$this->createProjectNginxDirectory();
(new NginxDockerFileBuilder($this->config))->build($input)->save();
}
(new DockerComposeFileBuilder($this->config))->build($input)->save();
}
/**
* @throws \Exception
*/
private function buildDockerfiles(InputInterface $input): void
{
(new PHPDockerFileBuilder($this->config))->build($input)->save();
}
/**
* @throws \Exception
*/
@ -166,13 +188,21 @@ class SpinCommand extends AbstractSpinnerCommand
/**
* @throws \Exception
*/
private function buildDockerfile(InputInterface $input): void
private function createProjectNginxDirectory(): void
{
(new PHPDockerFileBuilder($this->config))->build($input)->save();
$projectData = $this->config->getFilePaths()->get('projectData');
if (!$projectData instanceof SpinnerFilePath) {
throw new \Exception('Invalid project data directory provided.');
}
if (!file_exists($projectData->getProvidedPath() . '/nginx')) {
mkdir($projectData->getProvidedPath() . '/nginx', 0777, true);
}
}
private function getPort(string $service): int
private function getPort(string $service): ?int
{
return $this->ports[$service] ?? $this->portGenerator->generateRandomPort();
return $this->ports[$service];
}
}