Spins up basic PHP container
This commit is contained in:
parent
b8ad06cda3
commit
00b593d6d3
7 changed files with 129 additions and 62 deletions
|
@ -1,3 +1,6 @@
|
||||||
PROJECT_DIRECTORY=%s
|
PROJECT_DIRECTORY=%s
|
||||||
PROJECT_NAME=%s
|
PROJECT_NAME=%s
|
||||||
PHP_VERSION=%s
|
PHP_VERSION=%s
|
||||||
|
|
||||||
|
# Ports
|
||||||
|
PHP_PORT=%s
|
|
@ -1,26 +0,0 @@
|
||||||
services:
|
|
||||||
# nginx:
|
|
||||||
# build:
|
|
||||||
# context: ./nginx
|
|
||||||
# ports:
|
|
||||||
# - ${NGINX_PORT}:80
|
|
||||||
# volumes:
|
|
||||||
# - ${PROJECT_DIRECTORY}:/var/www/html:cached
|
|
||||||
# - ./nginx/conf.d:/etc/nginx/conf.d
|
|
||||||
# database:
|
|
||||||
# image: mysql:8.0
|
|
||||||
# command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
|
|
||||||
# ports:
|
|
||||||
# - ${MYSQL_PORT}:3306
|
|
||||||
# expose:
|
|
||||||
# - "3306"
|
|
||||||
# environment:
|
|
||||||
# MYSQL_ROOT_PASSWORD: docker
|
|
||||||
# volumes:
|
|
||||||
# - ./data/${PROJECT_NAME}/mysql:/var/lib/mysql:cached
|
|
||||||
# cache:
|
|
||||||
# image: redis:latest
|
|
||||||
# ports:
|
|
||||||
# - ${REDIS_PORT}:6379
|
|
||||||
# volumes:
|
|
||||||
# - ./data/${PROJECT_NAME}/redis:/data:cached
|
|
|
@ -1,7 +1,3 @@
|
||||||
ARG PHP_VERSION
|
|
||||||
|
|
||||||
ENV PHP_VERSION ${PHP_VERSION}
|
|
||||||
|
|
||||||
FROM php:${PHP_VERSION}-fpm
|
FROM php:${PHP_VERSION}-fpm
|
||||||
|
|
||||||
RUN mkdir -p /var/www/html
|
RUN mkdir -p /var/www/html
|
||||||
|
@ -13,29 +9,29 @@ RUN apt-get -qq update && apt-get -qq install -y \
|
||||||
zip \
|
zip \
|
||||||
unzip \
|
unzip \
|
||||||
libicu-dev \
|
libicu-dev \
|
||||||
imagick \
|
|
||||||
nano \
|
nano \
|
||||||
bash \
|
bash \
|
||||||
dnsutils
|
dnsutils
|
||||||
|
|
||||||
ENV NVM_DIR /root/.nvm
|
#ENV NVM_DIR /root/.nvm
|
||||||
ENV NODE_VERSION 20
|
#ENV NODE_VERSION 20
|
||||||
|
#
|
||||||
RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
|
#RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash \
|
||||||
&& . "$NVM_DIR/nvm.sh" \
|
# && . "$NVM_DIR/nvm.sh" \
|
||||||
&& nvm install $NODE_VERSION \
|
# && nvm install $NODE_VERSION \
|
||||||
&& nvm use $NODE_VERSION
|
# && nvm use $NODE_VERSION
|
||||||
|
#
|
||||||
COPY --from=node:20 /usr/local/bin/npx /usr/local/bin/npx
|
#COPY --from=node:20 /usr/local/bin/npx /usr/local/bin/npx
|
||||||
|
|
||||||
RUN docker-php-ext-configure intl > /dev/null
|
RUN docker-php-ext-configure intl > /dev/null
|
||||||
RUN docker-php-ext-install mysqli pdo pdo_mysql sockets intl exif bcmath opcache > /dev/null
|
RUN docker-php-ext-install mysqli pdo pdo_mysql sockets intl exif bcmath > /dev/null
|
||||||
|
|
||||||
RUN pecl install xdebug redis \
|
#RUN pecl install xdebug redis \
|
||||||
&& docker-php-ext-enable redis
|
# && docker-php-ext-enable redis
|
||||||
|
|
||||||
COPY ./xdebug.ini.tmp "${PHP_INI_DIR}/conf.d/xdebug.ini"
|
#COPY ./xdebug.ini.tmp "${PHP_INI_DIR}/conf.d/xdebug.ini"
|
||||||
COPY ./opcache.ini "${PHP_INI_DIR}/conf.d"
|
#RUN docker-php-ext-install opcache > /dev/null
|
||||||
|
#COPY ./opcache.ini "${PHP_INI_DIR}/conf.d"
|
||||||
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
|
COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
|
||||||
|
|
||||||
WORKDIR /var/www/html
|
WORKDIR /var/www/html
|
|
@ -1,10 +1,13 @@
|
||||||
php:
|
services:
|
||||||
build:
|
php:
|
||||||
context: ./php-fpm
|
build:
|
||||||
working_dir: /var/www/html
|
context: ./php-fpm
|
||||||
extra_hosts:
|
args:
|
||||||
- host.docker.internal:host-gateway
|
PHP_VERSION: ${PHP_VERSION}
|
||||||
volumes:
|
working_dir: /var/www/html
|
||||||
- ${PROJECT_DIRECTORY}:/var/www/html:cached
|
extra_hosts:
|
||||||
ports:
|
- host.docker.internal:host-gateway
|
||||||
- ${PHP_PORT}:9003
|
volumes:
|
||||||
|
- ${PROJECT_DIRECTORY}:/var/www/html:cached
|
||||||
|
ports:
|
||||||
|
- ${PHP_PORT}:9003
|
31
src/Classes/OS/PortGenerator.php
Normal file
31
src/Classes/OS/PortGenerator.php
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Loom\Spinner\Classes\OS;
|
||||||
|
|
||||||
|
class PortGenerator
|
||||||
|
{
|
||||||
|
public function generateRandomPort(): int
|
||||||
|
{
|
||||||
|
$port = 0;
|
||||||
|
$portInUse = true;
|
||||||
|
|
||||||
|
while ($portInUse) {
|
||||||
|
$port = rand(49152, 65535);
|
||||||
|
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||||||
|
|
||||||
|
if (!$socket) {
|
||||||
|
throw new \RuntimeException('Failed to create socket: ' . socket_strerror(socket_last_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@socket_bind($socket, '127.0.0.1', $port)) {
|
||||||
|
$portInUse = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket_close($socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $port;
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,6 +63,10 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
|
||||||
new SpinnerFilePath(sprintf('data/environments/%s/.env', $input->getArgument('name'))),
|
new SpinnerFilePath(sprintf('data/environments/%s/.env', $input->getArgument('name'))),
|
||||||
'projectEnv'
|
'projectEnv'
|
||||||
);
|
);
|
||||||
|
$this->filePaths->add(
|
||||||
|
new SpinnerFilePath(sprintf('data/environments/%s/docker-compose.yml', $input->getArgument('name'))),
|
||||||
|
'projectDockerCompose'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
|
@ -83,11 +87,10 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
|
||||||
protected function buildDockerComposeCommand(string $command, bool $daemon = true): string
|
protected function buildDockerComposeCommand(string $command, bool $daemon = true): string
|
||||||
{
|
{
|
||||||
return sprintf(
|
return sprintf(
|
||||||
'cd %s && docker compose %s --env-file=%s%s',
|
'cd %s && docker-compose --env-file=%s %s%s',
|
||||||
$this->filePaths->get('config')->getAbsolutePath(),
|
$this->filePaths->get('projectData')->getAbsolutePath(),
|
||||||
|
$this->filePaths->get('projectEnv')->getAbsolutePath(),
|
||||||
$command,
|
$command,
|
||||||
$this->filePaths->get('projectEnv')->getAbsolutePath()
|
|
||||||
?? $this->filePaths->get('projectEnv')->getProvidedPath(),
|
|
||||||
$daemon ? ' -d' : ''
|
$daemon ? ' -d' : ''
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -118,6 +121,9 @@ class AbstractSpinnerCommand extends Command implements ConsoleCommandInterface
|
||||||
'defaultSpinnerConfig' => new SpinnerFilePath('config/spinner.yaml'),
|
'defaultSpinnerConfig' => new SpinnerFilePath('config/spinner.yaml'),
|
||||||
'envTemplate' => new SpinnerFilePath('config/.template.env'),
|
'envTemplate' => new SpinnerFilePath('config/.template.env'),
|
||||||
'data' => new SpinnerFilePath('data'),
|
'data' => new SpinnerFilePath('data'),
|
||||||
|
'phpYamlTemplate' => new SpinnerFilePath('config/php.yaml'),
|
||||||
|
'phpFpmDockerfileTemplate' => new SpinnerFilePath('config/php-fpm/Dockerfile'),
|
||||||
|
'phpFpmDataDirectory' => new SpinnerFilePath('config/php-fpm'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,16 +4,31 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace Loom\Spinner\Command;
|
namespace Loom\Spinner\Command;
|
||||||
|
|
||||||
|
use Loom\Spinner\Classes\OS\PortGenerator;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputArgument;
|
use Symfony\Component\Console\Input\InputArgument;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
use Symfony\Component\Yaml\Yaml;
|
||||||
|
|
||||||
#[AsCommand(name: 'spin:up', description: 'Spin up a new development environment')]
|
#[AsCommand(name: 'spin:up', description: 'Spin up a new development environment')]
|
||||||
class SpinCommand extends AbstractSpinnerCommand
|
class SpinCommand extends AbstractSpinnerCommand
|
||||||
{
|
{
|
||||||
|
private PortGenerator $portGenerator;
|
||||||
|
private array $ports;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->portGenerator = new PortGenerator();
|
||||||
|
$this->ports = [
|
||||||
|
'php' => $this->portGenerator->generateRandomPort(),
|
||||||
|
];
|
||||||
|
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
|
@ -39,18 +54,57 @@ class SpinCommand extends AbstractSpinnerCommand
|
||||||
|
|
||||||
$this->style->success("Spinning up a new development environment...");
|
$this->style->success("Spinning up a new development environment...");
|
||||||
|
|
||||||
|
$this->createProjectData($input);
|
||||||
|
|
||||||
|
$command = $this->buildDockerComposeCommand(sprintf('-p %s up', $input->getArgument('name')));
|
||||||
|
|
||||||
|
passthru($command);
|
||||||
|
|
||||||
|
return Command::SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createProjectData(InputInterface $input): void
|
||||||
|
{
|
||||||
mkdir($this->filePaths->get('projectData')->getProvidedPath(), 0777, true);
|
mkdir($this->filePaths->get('projectData')->getProvidedPath(), 0777, true);
|
||||||
|
|
||||||
|
$this->createEnvironmentFile($input);
|
||||||
|
$this->buildDockerComposeFile($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createEnvironmentFile(InputInterface $input): void
|
||||||
|
{
|
||||||
file_put_contents(
|
file_put_contents(
|
||||||
$this->filePaths->get('projectEnv')->getProvidedPath(),
|
$this->filePaths->get('projectEnv')->getProvidedPath(),
|
||||||
sprintf(
|
sprintf(
|
||||||
file_get_contents($this->filePaths->get('envTemplate')->getAbsolutePath()),
|
file_get_contents($this->filePaths->get('envTemplate')->getAbsolutePath()),
|
||||||
$this->filePaths->get('project')->getAbsolutePath(),
|
$this->filePaths->get('project')->getAbsolutePath(),
|
||||||
$input->getArgument('name'),
|
$input->getArgument('name'),
|
||||||
$input->getOption('php')
|
$input->getOption('php'),
|
||||||
|
$this->getPort('php'),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Command::SUCCESS;
|
private function buildDockerComposeFile(InputInterface $input): void
|
||||||
|
{
|
||||||
|
if (!file_exists($this->filePaths->get('projectData')->getProvidedPath() . '/php-fpm')) {
|
||||||
|
mkdir($this->filePaths->get('projectData')->getProvidedPath() . '/php-fpm', 0777, true);
|
||||||
|
}
|
||||||
|
file_put_contents(
|
||||||
|
$this->filePaths->get('projectDockerCompose')->getProvidedPath(),
|
||||||
|
file_get_contents($this->filePaths->get('phpYamlTemplate')->getAbsolutePath())
|
||||||
|
);
|
||||||
|
$phpFpmDockerfileTemplate = file_get_contents($this->filePaths->get('phpFpmDockerfileTemplate')->getAbsolutePath());
|
||||||
|
$phpFpmDockerfileTemplate = str_replace('${PHP_VERSION}', $input->getOption('php'), $phpFpmDockerfileTemplate);
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
$this->filePaths->get('projectData')->getProvidedPath() . '/php-fpm/Dockerfile',
|
||||||
|
$phpFpmDockerfileTemplate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPort(string $service): int
|
||||||
|
{
|
||||||
|
return $this->ports[$service] ?? $this->portGenerator->generateRandomPort();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue