diff --git a/.env.example b/.env.example index 773f95c9a..fd6be2e87 100644 --- a/.env.example +++ b/.env.example @@ -294,8 +294,4 @@ WEB_PATH= # wiki WIKI_LOGIN="${APP_URL}:3000/login" WIKI_RESET_PASSWORD="${APP_URL}:3000/reset-password" -WIKI_EXTERNAL_PROFILE="${APP_URL}:3000/external" - -SAIL_XDEBUG_MODE=off -XDEBUG_MODE=off -OCTANE_SERVER=frankenphp \ No newline at end of file +WIKI_EXTERNAL_PROFILE="${APP_URL}:3000/external" \ No newline at end of file diff --git a/.gitignore b/.gitignore index ca7a4601b..c55cc9bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,3 @@ public/js/app.js test.php docker-compose.yml docker-data -**/caddy -frankenphp -frankenphp-worker.php diff --git a/Dockerfile b/Dockerfile index 04e44a0e9..676887866 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,83 @@ -FROM dunglas/frankenphp:php8.5 AS production +FROM php:8.5-fpm AS builder RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ - ffmpeg \ - default-mysql-client \ - git \ + curl \ unzip \ - && install-php-extensions \ + git \ + libonig-dev \ + libssl-dev \ + libxml2-dev \ + libcurl4-openssl-dev \ + libicu-dev \ + libzip-dev \ + libpng-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + && docker-php-ext-configure gd \ + --with-freetype \ + --with-jpeg \ + && docker-php-ext-install -j$(nproc) \ pdo_mysql \ intl \ zip \ bcmath \ gd \ pcntl \ - igbinary \ - redis \ + && pecl install igbinary \ + && docker-php-ext-enable igbinary \ + && pecl install redis \ + && docker-php-ext-enable redis \ + && apt-get autoremove -y \ && apt-get clean \ - && rm -rf /var/lib/apt/lists/* + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* WORKDIR /app +COPY . /app + +RUN cp .env.example .env + COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer -COPY --chown=www-data:www-data . /app +RUN composer install \ + --no-dev \ + --optimize-autoloader \ + --no-interaction \ + --no-progress \ + --prefer-dist -RUN cp .env.example .env \ - && composer install \ - --no-dev \ - --optimize-autoloader \ - --no-interaction \ - --no-progress \ - --prefer-dist \ - && rm -f .env \ - && chown -R www-data:www-data /app/storage /app/bootstrap/cache +RUN rm -f .env + +FROM php:8.5-fpm AS production + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + ffmpeg \ + default-mysql-client \ + libicu76 \ + libzip5 \ + libpng16-16t64 \ + libjpeg62-turbo \ + libfreetype6 \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +COPY --from=builder /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/ +COPY --from=builder /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/ + +RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" COPY docker/production/php.ini /usr/local/etc/php/conf.d/99-app.ini -USER www-data \ No newline at end of file +COPY --from=builder /app /app + +WORKDIR /app + +RUN chown -R www-data:www-data /app + +USER www-data + +EXPOSE 9000 + +CMD ["php-fpm"] \ No newline at end of file diff --git a/composer.json b/composer.json index bbc1799cb..b2a94b390 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,6 @@ "laravel-notification-channels/discord": "^1.8", "laravel/fortify": "^1.39.0", "laravel/framework": "^13.29.0", - "laravel/octane": "^2.19", "laravel/pennant": "^1.26.0", "laravel/pulse": "^1.8.1", "laravel/sanctum": "^4.3.3", diff --git a/composer.lock b/composer.lock index f72f31c71..2d94e0697 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "42f75be64056139d8b17c7bd5bebac30", + "content-hash": "cf8948bbcd1a53d101c87954ae6f9aa3", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -3667,94 +3667,6 @@ ], "time": "2026-02-24T04:15:24+00:00" }, - { - "name": "laminas/laminas-diactoros", - "version": "3.8.0", - "source": { - "type": "git", - "url": "https://github.com/laminas/laminas-diactoros.git", - "reference": "60c182916b2749480895601649563970f3f12ec4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laminas/laminas-diactoros/zipball/60c182916b2749480895601649563970f3f12ec4", - "reference": "60c182916b2749480895601649563970f3f12ec4", - "shasum": "" - }, - "require": { - "php": "~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0", - "psr/http-factory": "^1.1", - "psr/http-message": "^1.1 || ^2.0" - }, - "conflict": { - "amphp/amp": "<2.6.4" - }, - "provide": { - "psr/http-factory-implementation": "^1.0", - "psr/http-message-implementation": "^1.1 || ^2.0" - }, - "require-dev": { - "ext-curl": "*", - "ext-dom": "*", - "ext-gd": "*", - "ext-libxml": "*", - "http-interop/http-factory-tests": "^2.2.0", - "laminas/laminas-coding-standard": "~3.1.0", - "php-http/psr7-integration-tests": "^1.4.0", - "phpunit/phpunit": "^10.5.36", - "psalm/plugin-phpunit": "^0.19.5", - "vimeo/psalm": "^6.13" - }, - "type": "library", - "extra": { - "laminas": { - "module": "Laminas\\Diactoros", - "config-provider": "Laminas\\Diactoros\\ConfigProvider" - } - }, - "autoload": { - "files": [ - "src/functions/create_uploaded_file.php", - "src/functions/marshal_headers_from_sapi.php", - "src/functions/marshal_method_from_sapi.php", - "src/functions/marshal_protocol_version_from_sapi.php", - "src/functions/normalize_server.php", - "src/functions/normalize_uploaded_files.php", - "src/functions/parse_cookie_header.php" - ], - "psr-4": { - "Laminas\\Diactoros\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "description": "PSR HTTP Message implementations", - "homepage": "https://laminas.dev", - "keywords": [ - "http", - "laminas", - "psr", - "psr-17", - "psr-7" - ], - "support": { - "chat": "https://laminas.dev/chat", - "docs": "https://docs.laminas.dev/laminas-diactoros/", - "forum": "https://discourse.laminas.dev", - "issues": "https://github.com/laminas/laminas-diactoros/issues", - "rss": "https://github.com/laminas/laminas-diactoros/releases.atom", - "source": "https://github.com/laminas/laminas-diactoros" - }, - "funding": [ - { - "url": "https://funding.communitybridge.org/projects/laminas-project", - "type": "community_bridge" - } - ], - "time": "2025-10-12T15:31:36+00:00" - }, { "name": "laragraph/utils", "version": "v2.3.1", @@ -4262,95 +4174,6 @@ }, "time": "2026-08-25T20:57:16+00:00" }, - { - "name": "laravel/octane", - "version": "v2.19.1", - "source": { - "type": "git", - "url": "https://github.com/laravel/octane.git", - "reference": "68a2516a0318baba0de0e4648f61e335c5e69dca" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/laravel/octane/zipball/68a2516a0318baba0de0e4648f61e335c5e69dca", - "reference": "68a2516a0318baba0de0e4648f61e335c5e69dca", - "shasum": "" - }, - "require": { - "laminas/laminas-diactoros": "^3.0", - "laravel/framework": "^10.10.1|^11.0|^12.0|^13.0", - "laravel/prompts": "^0.1.24|^0.2.0|^0.3.0", - "laravel/serializable-closure": "^1.3|^2.0", - "nesbot/carbon": "^2.66.0|^3.0", - "php": "^8.1.0", - "symfony/console": "^6.0|^7.0|^8.0", - "symfony/psr-http-message-bridge": "^2.2.0|^6.4|^7.0|^8.0" - }, - "conflict": { - "spiral/roadrunner": "<2023.1.0", - "spiral/roadrunner-cli": "<2.6.0", - "spiral/roadrunner-http": "<3.3.0" - }, - "require-dev": { - "guzzlehttp/guzzle": "^7.6.1", - "inertiajs/inertia-laravel": "^1.3.2|^2.0", - "laravel/scout": "^10.2.1", - "laravel/socialite": "^5.6.1", - "livewire/livewire": "^2.12.3|^3.0", - "nunomaduro/collision": "^6.4.0|^7.5.2|^8.0", - "orchestra/testbench": "^8.21|^9.0|^10.0|^11.0", - "phpstan/phpstan": "^2.1.7", - "phpunit/phpunit": "^10.4|^11.5|^12.0|^13.0", - "spiral/roadrunner-cli": "^2.6.0", - "spiral/roadrunner-http": "^3.3.0" - }, - "bin": [ - "bin/roadrunner-worker", - "bin/swoole-server" - ], - "type": "library", - "extra": { - "laravel": { - "aliases": { - "Octane": "Laravel\\Octane\\Facades\\Octane" - }, - "providers": [ - "Laravel\\Octane\\OctaneServiceProvider" - ] - }, - "branch-alias": { - "dev-master": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "Laravel\\Octane\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Taylor Otwell", - "email": "taylor@laravel.com" - } - ], - "description": "Supercharge your Laravel application's performance.", - "keywords": [ - "frankenphp", - "laravel", - "octane", - "roadrunner", - "swoole" - ], - "support": { - "issues": "https://github.com/laravel/octane/issues", - "source": "https://github.com/laravel/octane" - }, - "time": "2026-08-13T13:58:52+00:00" - }, { "name": "laravel/passkeys", "version": "v0.2.1", @@ -12656,93 +12479,6 @@ ], "time": "2026-08-21T17:47:34+00:00" }, - { - "name": "symfony/psr-http-message-bridge", - "version": "v8.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/psr-http-message-bridge.git", - "reference": "67fd34de15ded1763aa1e330fe345f080a94022c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/67fd34de15ded1763aa1e330fe345f080a94022c", - "reference": "67fd34de15ded1763aa1e330fe345f080a94022c", - "shasum": "" - }, - "require": { - "php": ">=8.4.1", - "psr/http-message": "^1.0|^2.0", - "symfony/http-foundation": "^7.4|^8.0" - }, - "conflict": { - "php-http/discovery": "<1.15" - }, - "require-dev": { - "nyholm/psr7": "^1.1", - "php-http/discovery": "^1.15", - "psr/log": "^1.1.4|^2|^3", - "symfony/browser-kit": "^7.4|^8.0", - "symfony/config": "^7.4|^8.0", - "symfony/event-dispatcher": "^7.4|^8.0", - "symfony/framework-bundle": "^7.4|^8.0", - "symfony/http-kernel": "^7.4|^8.0", - "symfony/runtime": "^7.4|^8.0" - }, - "type": "symfony-bridge", - "autoload": { - "psr-4": { - "Symfony\\Bridge\\PsrHttpMessage\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "PSR HTTP message bridge", - "homepage": "https://symfony.com", - "keywords": [ - "http", - "http-message", - "psr-17", - "psr-7" - ], - "support": { - "source": "https://github.com/symfony/psr-http-message-bridge/tree/v8.1.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://github.com/nicolas-grekas", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2026-05-29T05:06:50+00:00" - }, { "name": "symfony/routing", "version": "v8.1.5", diff --git a/config/octane.php b/config/octane.php deleted file mode 100644 index 193d7db69..000000000 --- a/config/octane.php +++ /dev/null @@ -1,239 +0,0 @@ - env('OCTANE_SERVER', 'frankenphp'), - - /* - |-------------------------------------------------------------------------- - | Force HTTPS - |-------------------------------------------------------------------------- - | - | When this configuration value is set to "true", Octane will inform the - | framework that all absolute links must be generated using the HTTPS - | protocol. Otherwise your links may be generated using plain HTTP. - | - */ - - 'https' => env('OCTANE_HTTPS', false), - - /* - |-------------------------------------------------------------------------- - | Octane Listeners - |-------------------------------------------------------------------------- - | - | All of the event listeners for Octane's events are defined below. These - | listeners are responsible for resetting your application's state for - | the next request. You may even add your own listeners to the list. - | - */ - - 'listeners' => [ - WorkerStarting::class => [ - EnsureUploadedFilesAreValid::class, - EnsureUploadedFilesCanBeMoved::class, - ], - - RequestReceived::class => [ - ...Octane::prepareApplicationForNextOperation(), - ...Octane::prepareApplicationForNextRequest(), - // - ], - - RequestHandled::class => [ - // - ], - - RequestTerminated::class => [ - // FlushUploadedFiles::class, - ], - - TaskReceived::class => [ - ...Octane::prepareApplicationForNextOperation(), - // - ], - - TaskTerminated::class => [ - // - ], - - TickReceived::class => [ - ...Octane::prepareApplicationForNextOperation(), - // - ], - - TickTerminated::class => [ - // - ], - - OperationTerminated::class => [ - FlushOnce::class, - FlushTemporaryContainerInstances::class, - // DisconnectFromDatabases::class, - // CollectGarbage::class, - ], - - WorkerErrorOccurred::class => [ - ReportException::class, - StopWorkerIfNecessary::class, - ], - - WorkerStopping::class => [ - CloseMonologHandlers::class, - ], - ], - - /* - |-------------------------------------------------------------------------- - | Warm / Flush Bindings - |-------------------------------------------------------------------------- - | - | The bindings listed below will either be pre-warmed when a worker boots - | or they will be flushed before every new request. Flushing a binding - | will force the container to resolve that binding again when asked. - | - */ - - 'warm' => [ - ...Octane::defaultServicesToWarm(), - ], - - 'flush' => [ - // - ], - - /* - |-------------------------------------------------------------------------- - | Octane Swoole Tables - |-------------------------------------------------------------------------- - | - | While using Swoole, you may define additional tables as required by the - | application. These tables can be used to store data that needs to be - | quickly accessed by other workers on the particular Swoole server. - | - */ - - 'tables' => [ - 'example:1000' => [ - 'name' => 'string:1000', - 'votes' => 'int', - ], - ], - - /* - |-------------------------------------------------------------------------- - | Octane Swoole Cache Table - |-------------------------------------------------------------------------- - | - | While using Swoole, you may leverage the Octane cache, which is powered - | by a Swoole table. You may set the maximum number of rows as well as - | the number of bytes per row using the configuration options below. - | - */ - - 'cache' => [ - 'rows' => 1000, - 'bytes' => 10000, - ], - - /* - |-------------------------------------------------------------------------- - | File Watching - |-------------------------------------------------------------------------- - | - | The following list of files and directories will be watched when using - | the --watch option offered by Octane. If any of the directories and - | files are changed, Octane will automatically reload your workers. - | - */ - - 'watch' => [ - 'app', - 'bootstrap', - 'config/**/*.php', - 'database/**/*.php', - 'public/**/*.php', - 'resources/**/*.php', - 'routes', - 'composer.lock', - '.env', - ], - - /* - |-------------------------------------------------------------------------- - | Garbage Collection Threshold - |-------------------------------------------------------------------------- - | - | When executing long-lived PHP scripts such as Octane, memory can build - | up before being cleared by PHP. You can force Octane to run garbage - | collection if your application consumes this amount of megabytes. - | - */ - - 'garbage' => 50, - - /* - |-------------------------------------------------------------------------- - | Maximum Execution Time - |-------------------------------------------------------------------------- - | - | The following setting configures the maximum execution time for requests - | being handled by Octane. You may set this value to 0 to indicate that - | there isn't a specific time limit on Octane request execution time. - | - */ - - 'max_execution_time' => 30, - - /* - |-------------------------------------------------------------------------- - | Octane Server State File - |-------------------------------------------------------------------------- - | - | This value determines where Octane stores the state file used to track - | the running server's master process ID and admin endpoint, which is - | read by various Octane commands. You may tweak this if necessary. - | - */ - - 'state_file' => env('OCTANE_STATE_FILE', storage_path('logs/octane-server-state.json')), - -]; diff --git a/docker-compose.beta.yml b/docker-compose.beta.yml index 3bd52c13d..da533fd1f 100644 --- a/docker-compose.beta.yml +++ b/docker-compose.beta.yml @@ -7,15 +7,10 @@ services: image: '${APP_IMAGE:-beta-animethemes-server:local}' container_name: beta-animethemes-server restart: unless-stopped - command: php artisan octane:frankenphp --host=0.0.0.0 --port=8000 --workers=1 --max-requests=500 ports: - - "127.0.0.1:${APP_PORT:-9001}:8000" + - "127.0.0.1:${APP_PORT:-9001}:9000" env_file: - .env - environment: - XDG_CONFIG_HOME: /tmp/config - XDG_DATA_HOME: /tmp/data - HOME: /tmp volumes: - laravel-storage:/app/storage networks: diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index dd9907c43..98e83f53c 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -7,15 +7,10 @@ services: image: '${APP_IMAGE:-animethemes-server:local}' container_name: animethemes-server restart: unless-stopped - command: php artisan octane:frankenphp --host=0.0.0.0 --port=8000 --workers=2 --max-requests=500 ports: - - "127.0.0.1:${APP_PORT:-9000}:8000" + - "127.0.0.1:${APP_PORT:-9000}:9000" env_file: - .env - environment: - XDG_CONFIG_HOME: /tmp/config - XDG_DATA_HOME: /tmp/data - HOME: /tmp volumes: - laravel-storage-production:/app/storage networks: