From acf87efdb9ca499d66bf2174709229e7af0acb21 Mon Sep 17 00:00:00 2001 From: Daniel Winning Date: Sun, 13 Apr 2025 20:07:48 +0100 Subject: [PATCH] Nginx setup --- .gitignore | 3 +- config/.template.env | 5 ++- config/nginx.yaml | 9 ++++ config/nginx/Dockerfile | 5 +++ config/nginx/conf.d/default.conf | 25 +++++++++++ config/spinner.yaml | 4 +- src/Classes/Config/Config.php | 18 +++++++- src/Classes/File/DockerComposeFileBuilder.php | 23 ++++++++++ .../File/Interface/DataPathInterface.php | 3 +- src/Classes/File/NginxDockerFileBuilder.php | 37 ++++++++++++++++ src/Classes/File/PHPDockerFileBuilder.php | 2 +- src/Command/AbstractSpinnerCommand.php | 8 +--- src/Command/SpinCommand.php | 44 ++++++++++++++++--- 13 files changed, 166 insertions(+), 20 deletions(-) create mode 100644 config/nginx.yaml create mode 100644 config/nginx/Dockerfile create mode 100644 config/nginx/conf.d/default.conf create mode 100644 src/Classes/File/NginxDockerFileBuilder.php diff --git a/.gitignore b/.gitignore index c37da9f..56adbc5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.idea /vendor -composer.lock \ No newline at end of file +composer.lock +/public/* \ No newline at end of file diff --git a/config/.template.env b/config/.template.env index 2b0b70d..77e79d6 100644 --- a/config/.template.env +++ b/config/.template.env @@ -4,4 +4,7 @@ PROJECT_NAME=%s # PHP PHP_VERSION=%s -PHP_PORT=%s \ No newline at end of file +PHP_PORT=%s + +# Nginx +NGINX_PORT=%s \ No newline at end of file diff --git a/config/nginx.yaml b/config/nginx.yaml new file mode 100644 index 0000000..a43e2bc --- /dev/null +++ b/config/nginx.yaml @@ -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 \ No newline at end of file diff --git a/config/nginx/Dockerfile b/config/nginx/Dockerfile new file mode 100644 index 0000000..6903350 --- /dev/null +++ b/config/nginx/Dockerfile @@ -0,0 +1,5 @@ +FROM nginx:1.23-alpine + +CMD ["nginx", "-g", "daemon off;"] + +EXPOSE 80 443 \ No newline at end of file diff --git a/config/nginx/conf.d/default.conf b/config/nginx/conf.d/default.conf new file mode 100644 index 0000000..237dbe3 --- /dev/null +++ b/config/nginx/conf.d/default.conf @@ -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; + } +} \ No newline at end of file diff --git a/config/spinner.yaml b/config/spinner.yaml index f6e8320..8a6b2c3 100644 --- a/config/spinner.yaml +++ b/config/spinner.yaml @@ -4,4 +4,6 @@ options: version: 8.4 node: enabled: true - version: 20 \ No newline at end of file + version: 23 + server: + enabled: true \ No newline at end of file diff --git a/src/Classes/Config/Config.php b/src/Classes/Config/Config.php index 45fb06c..7a52b9d 100644 --- a/src/Classes/Config/Config.php +++ b/src/Classes/Config/Config.php @@ -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'), ]); } diff --git a/src/Classes/File/DockerComposeFileBuilder.php b/src/Classes/File/DockerComposeFileBuilder.php index 31738bf..60f39b0 100644 --- a/src/Classes/File/DockerComposeFileBuilder.php +++ b/src/Classes/File/DockerComposeFileBuilder.php @@ -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 + ); + } } \ No newline at end of file diff --git a/src/Classes/File/Interface/DataPathInterface.php b/src/Classes/File/Interface/DataPathInterface.php index 1f71075..16e201f 100644 --- a/src/Classes/File/Interface/DataPathInterface.php +++ b/src/Classes/File/Interface/DataPathInterface.php @@ -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'; } \ No newline at end of file diff --git a/src/Classes/File/NginxDockerFileBuilder.php b/src/Classes/File/NginxDockerFileBuilder.php new file mode 100644 index 0000000..acbf58c --- /dev/null +++ b/src/Classes/File/NginxDockerFileBuilder.php @@ -0,0 +1,37 @@ +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; + } +} \ No newline at end of file diff --git a/src/Classes/File/PHPDockerFileBuilder.php b/src/Classes/File/PHPDockerFileBuilder.php index 16af2c8..5018a7b 100644 --- a/src/Classes/File/PHPDockerFileBuilder.php +++ b/src/Classes/File/PHPDockerFileBuilder.php @@ -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() ); } } \ No newline at end of file diff --git a/src/Command/AbstractSpinnerCommand.php b/src/Command/AbstractSpinnerCommand.php index 32603d3..dffa13e 100644 --- a/src/Command/AbstractSpinnerCommand.php +++ b/src/Command/AbstractSpinnerCommand.php @@ -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'), diff --git a/src/Command/SpinCommand.php b/src/Command/SpinCommand.php index 4f69cf5..7482801 100644 --- a/src/Command/SpinCommand.php +++ b/src/Command/SpinCommand.php @@ -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); } /** @@ -133,6 +141,7 @@ class SpinCommand extends AbstractSpinnerCommand $input->getArgument('name'), $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,9 +188,17 @@ 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