From a92c15e50c3f862bc9e835b8b6684e87fc52e124 Mon Sep 17 00:00:00 2001 From: Lucas Pirola Date: Mon, 6 May 2024 17:33:22 -0300 Subject: [PATCH] Adiciona RoadRunner como alternativa de web server --- .env.example | 3 ++ app.php | 32 ++++++++++++ containers/config.d/.gitkeep | 0 containers/config.d/0.main.php | 30 +++++++++++ containers/config.d/auth.php | 43 ++++++++++++++++ containers/config.d/cache.php | 12 +++++ containers/config.d/log.php | 56 +++++++++++++++++++++ containers/config.d/middlewares.php | 6 +++ containers/config.d/plugins.php | 7 +++ containers/roadrunner/Dockerfile | 45 +++++++++++++++++ containers/roadrunner/config/.rr.yaml | 20 ++++++++ docker-compose.yml | 35 +++++++++++++ src/.dockerignore | 24 +++++++++ src/Dockerfile | 33 ++++++++++++ src/ErrorHandlingMiddleware.php | 37 ++++++++++++++ task | 72 +++++++++++++++++++++++++++ worker.php | 22 ++++++++ 17 files changed, 477 insertions(+) create mode 100644 .env.example create mode 100644 app.php create mode 100644 containers/config.d/.gitkeep create mode 100644 containers/config.d/0.main.php create mode 100644 containers/config.d/auth.php create mode 100644 containers/config.d/cache.php create mode 100644 containers/config.d/log.php create mode 100644 containers/config.d/middlewares.php create mode 100644 containers/config.d/plugins.php create mode 100644 containers/roadrunner/Dockerfile create mode 100644 containers/roadrunner/config/.rr.yaml create mode 100644 docker-compose.yml create mode 100644 src/.dockerignore create mode 100644 src/Dockerfile create mode 100644 src/ErrorHandlingMiddleware.php create mode 100755 task create mode 100644 worker.php diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000..a5c086a46b --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +RR_VERSION=2024.1.0 +PHP_IMAGE_VERSION=8.1-cli-alpine + diff --git a/app.php b/app.php new file mode 100644 index 0000000000..d34d191d20 --- /dev/null +++ b/app.php @@ -0,0 +1,32 @@ +addDefinitions([ + Psr\Http\Message\ResponseFactoryInterface::class => $psr17Factory, + Psr\Http\Message\ServerRequestFactoryInterface::class => $psr17Factory, + Psr\Http\Message\StreamFactoryInterface::class => $psr17Factory, + Psr\Http\Message\UploadedFileFactoryInterface::class => $psr17Factory, + Spiral\RoadRunner\WorkerInterface::class => Spiral\RoadRunner\Worker::create(), + Spiral\RoadRunner\Http\PSR7WorkerInterface::class => DI\autowire(Spiral\RoadRunner\Http\PSR7Worker::class), +]); +$container = $containerBuilder->build(); + +$app = DI\Bridge\Slim\Bridge::create($container); +// define routes +$app->get('/', function (Psr\Http\Message\ServerRequestInterface $request, Psr\Http\Message\ResponseInterface $response) { + $config = require_once(__DIR__ . '/src/conf/config.php'); + $container2 = MapasCulturais\App::i('web'); + $container2->init($config); + + return $container2->run(); + // $response->getBody()->write('Hello world from RoadRunner and Slim!'); + // return $response; +}); + +// set routing error handling +$app->add(App\ErrorHandlingMiddleware::class); + +return $app; \ No newline at end of file diff --git a/containers/config.d/.gitkeep b/containers/config.d/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/containers/config.d/0.main.php b/containers/config.d/0.main.php new file mode 100644 index 0000000000..4289d2e7aa --- /dev/null +++ b/containers/config.d/0.main.php @@ -0,0 +1,30 @@ + 'MapasCulturais\Themes\BaseV2', + 'app.mode' => $_ENV['APP_MODE'], + 'doctrine.isDev' => false, // deixe true somente se estiver trabalhando nos mapeamentos das entidades + + /* SELOS */ + 'app.verifiedSealsIds' => [1], + + /* ASSET MANAGER */ + 'themes.assetManager' => new \MapasCulturais\AssetManagers\FileSystem([ + 'publishPath' => BASE_PATH . 'assets/', + + 'mergeScripts' => $__process_assets, + 'mergeStyles' => $__process_assets, + + 'process.js' => !$__process_assets ? + 'cp {IN} {OUT}': + 'terser {IN} --source-map --output {OUT} ', + + 'process.css' => !$__process_assets ? + 'cp {IN} {OUT}': + 'uglifycss {IN} > {OUT}', + + 'publishFolderCommand' => 'cp -R {IN} {PUBLISH_PATH}{FILENAME}' + ]), +]; diff --git a/containers/config.d/auth.php b/containers/config.d/auth.php new file mode 100644 index 0000000000..95ed380973 --- /dev/null +++ b/containers/config.d/auth.php @@ -0,0 +1,43 @@ + 'Fake', + // 'auth.provider' => '\MultipleLocalAuth\Provider', + 'auth.config' => [ + 'salt' => env('AUTH_SALT', null), + 'timeout' => '24 hours', + 'strategies' => [ + 'Facebook' => [ + 'app_id' => env('AUTH_FACEBOOK_APP_ID', null), + 'app_secret' => env('AUTH_FACEBOOK_APP_SECRET', null), + 'scope' => env('AUTH_FACEBOOK_SCOPE', 'email'), + ], + 'LinkedIn' => [ + 'api_key' => env('AUTH_LINKEDIN_API_KEY', null), + 'secret_key' => env('AUTH_LINKEDIN_SECRET_KEY', null), + 'redirect_uri' => '/autenticacao/linkedin/oauth2callback', + 'scope' => env('AUTH_LINKEDIN_SCOPE', 'r_emailaddress') + ], + 'Google' => [ + 'client_id' => env('AUTH_GOOGLE_CLIENT_ID', null), + 'client_secret' => env('AUTH_GOOGLE_CLIENT_SECRET', null), + 'redirect_uri' => '/autenticacao/google/oauth2callback', + 'scope' => env('AUTH_GOOGLE_SCOPE', 'email'), + ], + 'Twitter' => [ + 'app_id' => env('AUTH_TWITTER_APP_ID', null), + 'app_secret' => env('AUTH_TWITTER_APP_SECRET', null), + ], + ] + ] + + //auth.provider' => 'MapasCulturais\AuthProviders\OpauthAuthentik', + //'auth.config' => [ + // 'salt' => env('AUTH_SALT', 'SECURITY_SALT'), + // 'timeout' => '24 hours', + // 'client_id' => env('AUTH_AUTHENTIK_APP_ID', ''), + // 'client_secret' => env('AUTH_AUTHENTIK_APP_SECRET', ''), + // 'scope' => env('AUTH_AUTHENTIK_SCOPE', 'openid profile email'), + // 'login_url' => env('AUTH_AUTHENTIK_LOGIN_URL', ''), + //] +]; diff --git a/containers/config.d/cache.php b/containers/config.d/cache.php new file mode 100644 index 0000000000..9afb3c1c7b --- /dev/null +++ b/containers/config.d/cache.php @@ -0,0 +1,12 @@ + false, + 'app.useAssetsUrlCache' => false, + // 'app.useFileUrlCache' => false, + // 'app.useEventsCache' => false, + // 'app.useSubsiteIdsCache' => false, + // 'app.usePermissionsCache' => false, + // 'app.useRegisterCache' => false, + // 'app.useApiCache' => false, +]; \ No newline at end of file diff --git a/containers/config.d/log.php b/containers/config.d/log.php new file mode 100644 index 0000000000..0771e06662 --- /dev/null +++ b/containers/config.d/log.php @@ -0,0 +1,56 @@ + env('LOG_LEVEL', 'DEBUG'), + + /* + Configuração dos handlers do monolog. + + se for uma string os handlers serão instanciados pela aplicação, + se for um array, a aplicação esperará que seja uma lista de handlers + + ex: 'file:WARNING,error_log:DEBUG,browser:DEBUG' + ex: [new \Monolog\Handler\ErrorLogHandler(level: Level::Debug)] + */ + 'monolog.handlers' => env('LOG_HANDLERS', 'error_log,browser'), + + 'monolog.processors' => [], + + /* + Pasta onde serão salvos os arquivos de log + + o padrão é ~/var/logs, onde ~ é a raíz do projeto, no docker é /var/www + */ + 'monolog.logsDir' => env('LOG_DIR', VAR_PATH . 'logs/'), + + // 'app.log.query' => true, + // 'app.log.hook' => true, + // 'app.log.requestData' => true, + // 'app.log.texts' => true, + // 'app.log.translations' => true, + // 'app.log.apiCache' => true, + // 'app.log.apiDql' => true, + // 'app.log.assets' => true, + // 'app.log.auth' => true, + + // 'app.log.components' => true, + // 'app.log.assetManager' => true, + + // 'app.log.jobs' => true, + // 'app.log.pcache' => true, + // 'app.log.pcache.users' => true, + + 'app.queryLogger' => env('LOG_QUERYLOG_CLASS', null) + +]; \ No newline at end of file diff --git a/containers/config.d/middlewares.php b/containers/config.d/middlewares.php new file mode 100644 index 0000000000..1f4911b70b --- /dev/null +++ b/containers/config.d/middlewares.php @@ -0,0 +1,6 @@ + [ + MapasCulturais\Middlewares\ExecutionTime::class + ] +]; \ No newline at end of file diff --git a/containers/config.d/plugins.php b/containers/config.d/plugins.php new file mode 100644 index 0000000000..895c9a8946 --- /dev/null +++ b/containers/config.d/plugins.php @@ -0,0 +1,7 @@ + [ + "MultipleLocalAuth" + ] +]; \ No newline at end of file diff --git a/containers/roadrunner/Dockerfile b/containers/roadrunner/Dockerfile new file mode 100644 index 0000000000..73b09cd202 --- /dev/null +++ b/containers/roadrunner/Dockerfile @@ -0,0 +1,45 @@ +ARG RR_VERSION +ARG RR_IMAGE=spiralscout/roadrunner:${RR_VERSION} +ARG PHP_IMAGE_VERSION +ARG PHP_IMAGE=php:${PHP_IMAGE_VERSION} + +FROM ${RR_IMAGE} as rr + +FROM ${PHP_IMAGE} + +RUN apk update && \ + apk add --no-cache --virtual wget zip unzip libzip-dev freetype-dev libjpeg-turbo-dev libpng-dev sqlite sqlite-dev openssl-dev \ + git bash freetype-dev \ + libpng-dev libjpeg-turbo-dev \ + libxml2-dev autoconf \ + g++ imagemagick-dev \ + libtool make postgresql-dev \ + libzip-dev curl-dev gnu-libiconv + + +RUN docker-php-ext-install zip \ + && docker-php-ext-install sockets \ + # && docker-php-ext-install opcache \ + && docker-php-ext-install pdo_pgsql \ + && docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ \ + && docker-php-ext-install -j$(nproc) gd \ + # && docker-php-ext-enable opcache \ + # && docker-php-ext-install gd \ + && docker-php-ext-install intl \ + && docker-php-ext-install opcache \ + && docker-php-ext-install xml \ + && docker-php-ext-install curl \ + # && docker-php-ext-install iconv \ + && docker-php-ext-install xmlwriter \ + && docker-php-ext-install simplexml + +# Copy Composer +COPY --from=composer:2 /usr/bin/composer /usr/bin/composer + +# Copy RoadRunner +COPY --from=rr /usr/bin/rr /usr/bin/rr + +# Copy RoadRunner config +COPY --from=rr /etc/rr.yaml /etc/rr.yaml + +CMD ["/usr/bin/rr", "serve", "-d", "-c", "/etc/rr.yaml"] diff --git a/containers/roadrunner/config/.rr.yaml b/containers/roadrunner/config/.rr.yaml new file mode 100644 index 0000000000..0e1c6b915a --- /dev/null +++ b/containers/roadrunner/config/.rr.yaml @@ -0,0 +1,20 @@ +version: "2.7" + +rpc: + listen: tcp://127.0.0.1:6001 +server: + command: "php /app/worker.php" + +http: + address: :8080 + pool: + num_workers: 4 + max_jobs: 64 + +reload: + interval: 1s + patterns: [ ".php" ] + services: + http: + recursive: true + dirs: [ "/app" ] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..71645bfcb0 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,35 @@ +services: + adminer: + image: adminer + ports: + - 8888:8080 + roadrunner: + build: + context: ./containers/roadrunner + args: + RR_VERSION: ${RR_VERSION} + PHP_IMAGE_VERSION: ${PHP_IMAGE_VERSION} + ports: + - 8080:8080 + environment: + RR_VERSION: ${RR_VERSION} + APP_MODE: development + working_dir: /app + volumes: + - ./:/app + - ./containers/roadrunner/config/.rr.yaml:/etc/rr.yaml:ro + + db: + image: postgis/postgis:14-master + environment: + - POSTGRES_PASSWORD=mapas + - POSTGRES_USER=mapas + - POSTGRES_DB=mapas + ports: + - "5432:5432" + volumes: + - postgis_data:/var/lib/postgresql/data + - ./dev/db:/docker-entrypoint-initdb.d + +volumes: + postgis_data: diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 0000000000..6d68aeaf5c --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,24 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md diff --git a/src/Dockerfile b/src/Dockerfile new file mode 100644 index 0000000000..62d17783c6 --- /dev/null +++ b/src/Dockerfile @@ -0,0 +1,33 @@ +FROM node:18-slim AS base +ENV PNPM_HOME="/pnpm" +ENV PATH="$PNPM_HOME:$PATH" +RUN corepack enable +# VOLUME [ "/app" ] +WORKDIR /app +# COPY package.json /app +# COPY pnpm* /app + +# FROM base AS prod-deps +# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive --prod --frozen-lockfile + +# FROM base AS build +# RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --recursive +# COPY src/ /app +# RUN pnpm run build + +# FROM base +# COPY --from=prod-deps /app/node_modules /app/node_modules +# COPY --from=build /app/dist /app/dist +# EXPOSE 8000 +# CMD [ "pnpm", "run", "watch" ] + +# FROM node:lts-alpine +# ENV NODE_ENV=production +# WORKDIR /usr/src/app +# COPY ["package.json", "package-lock.json*", "npm-shrinkwrap.json*", "./"] +# RUN npm install --production --silent && mv node_modules ../ +# COPY . . +# EXPOSE 3000 +# RUN chown -R node /usr/src/app +# USER node +# CMD ["npm", "start"] diff --git a/src/ErrorHandlingMiddleware.php b/src/ErrorHandlingMiddleware.php new file mode 100644 index 0000000000..f7c897479a --- /dev/null +++ b/src/ErrorHandlingMiddleware.php @@ -0,0 +1,37 @@ +responseFactory = $responseFactory; + } + + public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface { + try { + return $handler->handle($request); + } catch (HttpNotFoundException $e) { + $response = $this->responseFactory->createResponse(404); + $response->getBody()->write('route not found'); + return $response; + } catch (HttpMethodNotAllowedException $e) { + $response = $this->responseFactory->createResponse(405); + $response->getBody()->write('method not allowed'); + return $response; + } + } +} \ No newline at end of file diff --git a/task b/task new file mode 100755 index 0000000000..df6826bfc5 --- /dev/null +++ b/task @@ -0,0 +1,72 @@ +#!/usr/bin/env bash + +# start containers +function up { + docker compose up -d $@ +} + +# stop containers +function down { + docker compose down +} + +# initialize application +function init { + echo "Stating Initialization..." + + echo "Copy .env file..." + cp -n .env.example .env + + echo "Build docker images..." + docker compose build + + echo "Install PHP dependencies..." + docker compose run roadrunner sh -c 'composer require spiral/roadrunner:${RR_VERSION}' + + echo "Initialization completed!" +} + +# login to container +function login { + container=${1:-roadrunner} + + echo "Attempt to login ${container} container..." + docker compose exec ${container} bash +} + +# show container logs +function logs { + docker compose logs $1 +} + +# execute RoadRunner command +function rr { + docker compose exec roadrunner rr -c /etc/rr.yaml $1 +} + +subcommand=$1 +shift + +case $subcommand in +up) + up $@ + ;; +down) + down + ;; +init) + init + ;; +login) + login $1 + ;; +logs) + logs $1 + ;; +rr) + rr $1 + ;; +*) + echo "help" + ;; +esac diff --git a/worker.php b/worker.php new file mode 100644 index 0000000000..39c043b4a4 --- /dev/null +++ b/worker.php @@ -0,0 +1,22 @@ +getContainer()->get(Spiral\RoadRunner\Http\PSR7WorkerInterface::class); + +while ($req = $psr7Worker->waitRequest()) { + try { + $res = $app->handle($req); + $psr7Worker->respond($res); + } catch (Throwable $e) { + $psr7Worker->getWorker()->error((string)$e); + } +}