feat: ci/cd
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
.git
|
||||||
|
.env
|
||||||
|
node_modules
|
||||||
|
vendor
|
||||||
|
storage/logs
|
||||||
|
docker-compose*.yml
|
||||||
+32
-80
@@ -1,98 +1,50 @@
|
|||||||
# ============================================================
|
|
||||||
# CD — Déploiement Continu
|
|
||||||
# Déclenche un déploiement uniquement sur push main.
|
|
||||||
#
|
|
||||||
# Le runner Gitea Actions tourne directement sur le serveur.
|
|
||||||
# Aucun SSH nécessaire — les commandes s'exécutent localement.
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
name: CD
|
name: CD
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- CI
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
name: 🚀 Déploiement production
|
name: 🚀 Déploiement production
|
||||||
|
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: 🔐 Configuration SSH
|
||||||
# ── 1. Mise à jour du code ───────────────────────────────
|
|
||||||
- name: 🔄 Mise à jour du code
|
|
||||||
run: |
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.DEPLOY_SSH_KEY }}" \
|
||||||
|
> ~/.ssh/id_ed25519
|
||||||
|
chmod 600 ~/.ssh/id_ed25519
|
||||||
|
|
||||||
|
ssh-keyscan \
|
||||||
|
-H "${{ secrets.DEPLOY_HOST }}" \
|
||||||
|
>> ~/.ssh/known_hosts
|
||||||
|
|
||||||
|
- name: 🚀 Deploy Docker
|
||||||
|
run: |
|
||||||
|
ssh \
|
||||||
|
-i ~/.ssh/id_ed25519 \
|
||||||
|
${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF'
|
||||||
set -e
|
set -e
|
||||||
|
echo "📂 Projet"
|
||||||
cd /data/docker/landing-api
|
cd /data/docker/landing-api
|
||||||
|
echo "⬇️ Pull nouvelle image"
|
||||||
|
docker compose pull
|
||||||
|
echo "🚀 Redémarrage"
|
||||||
|
docker compose up -d
|
||||||
|
echo "🗄️ Migration Laravel"
|
||||||
|
|
||||||
echo "🔄 Pull depuis Gitea..."
|
docker compose exec -T app \
|
||||||
git fetch origin main
|
php artisan migrate --force
|
||||||
git reset --hard origin/main
|
|
||||||
|
|
||||||
# ── 2. Build de l'image Docker ───────────────────────────
|
echo "🧹 Nettoyage"
|
||||||
- name: 🐳 Build image Docker
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
cd /data/docker/landing-api
|
|
||||||
|
|
||||||
echo "🏗️ Build de l'image de production..."
|
|
||||||
docker compose -f compose.prod.yaml build --no-cache app
|
|
||||||
|
|
||||||
# ── 3. Démarrage / redémarrage des containers ────────────
|
|
||||||
- name: 🚀 Déploiement des containers
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
cd /data/docker/landing-api
|
|
||||||
|
|
||||||
echo "🚀 Redémarrage des services..."
|
|
||||||
docker compose -f compose.prod.yaml up -d --remove-orphans
|
|
||||||
|
|
||||||
# ── 4. Migrations base de données ────────────────────────
|
|
||||||
- name: 🗄️ Migrations base de données
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
cd /data/docker/landing-api
|
|
||||||
|
|
||||||
echo "⏳ Attente que la BDD soit prête..."
|
|
||||||
sleep 5
|
|
||||||
|
|
||||||
echo "🗄️ Exécution des migrations..."
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan migrate --force
|
|
||||||
|
|
||||||
# ── 5. Optimisations Laravel ─────────────────────────────
|
|
||||||
- name: ⚙️ Optimisations Laravel
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
cd /data/docker/landing-api
|
|
||||||
|
|
||||||
echo "⚙️ Mise en cache des configs, routes, vues..."
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan config:cache
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan route:cache
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan view:cache
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan event:cache
|
|
||||||
|
|
||||||
echo "🔄 Redémarrage des workers..."
|
|
||||||
docker compose -f compose.prod.yaml exec -T app php artisan queue:restart
|
|
||||||
|
|
||||||
# ── 6. Nettoyage des anciennes images ────────────────────
|
|
||||||
- name: 🧹 Nettoyage Docker
|
|
||||||
run: |
|
|
||||||
docker image prune -f
|
docker image prune -f
|
||||||
|
|
||||||
# ── 7. Résultat ──────────────────────────────────────────
|
echo "✅ Déploiement terminé"
|
||||||
- name: 🎉 Déploiement réussi
|
|
||||||
if: success()
|
|
||||||
run: |
|
|
||||||
echo "✅ Application déployée avec succès !"
|
|
||||||
echo "🔗 Commit : ${{ github.sha }}"
|
|
||||||
echo "👤 Par : ${{ github.actor }}"
|
|
||||||
|
|
||||||
- name: ❌ Déploiement échoué
|
EOF
|
||||||
if: failure()
|
|
||||||
run: |
|
|
||||||
echo "❌ Le déploiement a échoué — rollback recommandé"
|
|
||||||
echo "🔗 Commit : ${{ github.sha }}"
|
|
||||||
# Affiche les logs des containers en erreur pour debug
|
|
||||||
cd /data/docker/landing-api
|
|
||||||
docker compose -f compose.prod.yaml logs --tail=50
|
|
||||||
|
|||||||
+90
-52
@@ -1,78 +1,116 @@
|
|||||||
# ============================================================
|
|
||||||
# CI — Intégration Continue
|
|
||||||
# Se déclenche sur chaque push et chaque Pull Request.
|
|
||||||
# Lance les tests PHPUnit avec SQLite en mémoire (rapide).
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
name: CI
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
|
||||||
- '**' # tous les branches
|
|
||||||
pull_request:
|
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- develop
|
- develop
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: 🧪 Tests Laravel (PHP ${{ matrix.php }})
|
name: 🧪 Tests Laravel
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
php: ['8.3'] # Ajoute d'autres versions si tu veux tester plusieurs PHP
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# ── 1. Récupère le code ─────────────────────────────────
|
- name: 📥 Checkout
|
||||||
- name: 📥 Checkout du code
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
- name: 🐘 Setup PHP
|
||||||
# ── 2. Configure PHP avec les extensions nécessaires ────
|
|
||||||
- name: 🐘 Setup PHP ${{ matrix.php }}
|
|
||||||
uses: shivammathur/setup-php@v2
|
uses: shivammathur/setup-php@v2
|
||||||
with:
|
with:
|
||||||
php-version: ${{ matrix.php }}
|
php-version: '8.3'
|
||||||
extensions: mbstring, bcmath, sqlite3, pdo_sqlite, pgsql, pdo_pgsql, xml, curl, zip, gd, intl
|
extensions: >
|
||||||
coverage: none # met "xdebug" ici si tu veux du coverage
|
bcmath,
|
||||||
|
ctype,
|
||||||
|
curl,
|
||||||
|
dom,
|
||||||
|
fileinfo,
|
||||||
|
mbstring,
|
||||||
|
openssl,
|
||||||
|
pdo,
|
||||||
|
tokenizer,
|
||||||
|
xml,
|
||||||
|
zip
|
||||||
|
coverage: none
|
||||||
|
|
||||||
|
|
||||||
# ── 3. Cache des dépendances Composer ───────────────────
|
|
||||||
- name: 📦 Cache Composer
|
- name: 📦 Cache Composer
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: vendor
|
path: ~/.composer/cache
|
||||||
key: composer-${{ matrix.php }}-${{ hashFiles('composer.lock') }}
|
key: composer-${{ hashFiles('composer.lock') }}
|
||||||
restore-keys: composer-${{ matrix.php }}-
|
|
||||||
|
|
||||||
# ── 4. Installe les dépendances PHP ─────────────────────
|
|
||||||
- name: 📦 Installation Composer
|
|
||||||
run: composer install --no-interaction --prefer-dist --optimize-autoloader --no-scripts
|
|
||||||
|
|
||||||
# ── 5. Prépare l'environnement .env de test ─────────────
|
- name: 📦 Install Composer dependencies
|
||||||
- name: ⚙️ Configuration .env
|
|
||||||
run: |
|
run: |
|
||||||
|
composer install \
|
||||||
|
--no-interaction \
|
||||||
|
--prefer-dist \
|
||||||
|
--no-progress
|
||||||
|
|
||||||
|
|
||||||
|
- name: ⚙️ Prepare Laravel
|
||||||
|
run: |
|
||||||
|
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# On écrase les variables critiques pour les tests
|
|
||||||
echo "APP_ENV=testing" >> .env
|
|
||||||
echo "APP_KEY=" >> .env
|
|
||||||
echo "DB_CONNECTION=sqlite" >> .env
|
|
||||||
echo "DB_DATABASE=:memory:" >> .env
|
|
||||||
echo "QUEUE_CONNECTION=sync" >> .env
|
|
||||||
echo "SESSION_DRIVER=array" >> .env
|
|
||||||
echo "CACHE_STORE=array" >> .env
|
|
||||||
echo "MAIL_MAILER=array" >> .env
|
|
||||||
echo "BROADCAST_CONNECTION=null" >> .env
|
|
||||||
|
|
||||||
# ── 6. Génère la clé d'application ──────────────────────
|
php artisan key:generate
|
||||||
- name: 🔑 Génération de la clé APP_KEY
|
|
||||||
run: php artisan key:generate --ansi
|
|
||||||
|
|
||||||
# ── 7. Exécute les migrations (SQLite :memory:) ─────────
|
touch database/database.sqlite
|
||||||
- name: 🗄️ Migrations
|
|
||||||
run: php artisan migrate --force --ansi
|
|
||||||
|
|
||||||
# ── 8. Lance les tests ───────────────────────────────────
|
php artisan migrate --force
|
||||||
- name: ✅ Tests PHPUnit
|
|
||||||
run: php artisan test --ansi
|
|
||||||
|
- name: 🧪 Run PHPUnit
|
||||||
|
run: |
|
||||||
|
php artisan test
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
docker:
|
||||||
|
|
||||||
|
|
||||||
|
name: 🐳 Build & Push Image
|
||||||
|
|
||||||
|
needs: test
|
||||||
|
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
|
||||||
|
- name: 📥 Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 🔐 Login Registry Gitea
|
||||||
|
run: |
|
||||||
|
|
||||||
|
docker login git.leonmorival.xyz \
|
||||||
|
-u "${{ secrets.REGISTRY_USER }}" \
|
||||||
|
-p "${{ secrets.REGISTRY_PASSWORD }}"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 🏗️ Build image
|
||||||
|
run: |
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
-t git.leonmorival.xyz/leonm/landing-api:latest \
|
||||||
|
-t git.leonmorival.xyz/leonm/landing-api:${{ github.sha }} \
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- name: 📤 Push image
|
||||||
|
run: |
|
||||||
|
|
||||||
|
docker push git.leonmorival.xyz/leonm/landing-api:latest
|
||||||
|
|
||||||
|
docker push git.leonmorival.xyz/leonm/landing-api:${{ github.sha }}
|
||||||
|
|||||||
@@ -25,3 +25,7 @@ _ide_helper.php
|
|||||||
Homestead.json
|
Homestead.json
|
||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
|
||||||
|
**/caddy
|
||||||
|
frankenphp
|
||||||
|
frankenphp-worker.php
|
||||||
|
|||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
FROM dunglas/frankenphp:php8.3-alpine
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
||||||
|
RUN install-php-extensions \
|
||||||
|
pdo_pgsql \
|
||||||
|
opcache \
|
||||||
|
pcntl \
|
||||||
|
zip \
|
||||||
|
intl
|
||||||
|
|
||||||
|
|
||||||
|
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
||||||
|
|
||||||
|
|
||||||
|
COPY composer.json composer.lock ./
|
||||||
|
|
||||||
|
|
||||||
|
RUN composer install \
|
||||||
|
--no-dev \
|
||||||
|
--no-interaction \
|
||||||
|
--prefer-dist \
|
||||||
|
--optimize-autoloader
|
||||||
|
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
RUN php artisan octane:install --server=frankenphp || true
|
||||||
|
|
||||||
|
|
||||||
|
RUN php artisan config:cache
|
||||||
|
RUN php artisan route:cache
|
||||||
|
RUN php artisan view:cache
|
||||||
|
|
||||||
|
|
||||||
|
RUN chown -R www-data:www-data storage bootstrap/cache
|
||||||
|
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
|
||||||
|
CMD [
|
||||||
|
"php",
|
||||||
|
"artisan",
|
||||||
|
"octane:start",
|
||||||
|
"--server=frankenphp",
|
||||||
|
"--host=0.0.0.0",
|
||||||
|
"--port=8000"
|
||||||
|
]
|
||||||
+29
-85
@@ -1,102 +1,46 @@
|
|||||||
# ============================================================
|
|
||||||
# Docker Compose — Production
|
|
||||||
#
|
|
||||||
# Architecture :
|
|
||||||
# [Nginx Proxy Manager] ──► [FrankenPHP app:80]
|
|
||||||
# │
|
|
||||||
# [PostgreSQL]
|
|
||||||
# [Queue Worker]
|
|
||||||
#
|
|
||||||
# Le réseau "proxy" est externe (géré par Nginx Proxy Manager).
|
|
||||||
# Dans NPM, configure un proxy host vers : http://landing-api-app:80
|
|
||||||
#
|
|
||||||
# Usage :
|
|
||||||
# docker compose -f compose.prod.yaml up -d
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
# ── Application FrankenPHP (web + PHP tout-en-un) ───────
|
|
||||||
app:
|
app:
|
||||||
build:
|
image: git.leonmorival.xyz/leon/landing-api:latest
|
||||||
context: .
|
container_name: landing-api
|
||||||
dockerfile: docker/Dockerfile.prod
|
|
||||||
image: landing-api:latest
|
|
||||||
container_name: landing-api-app
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
|
||||||
APP_ENV: production
|
|
||||||
APP_DEBUG: "false"
|
|
||||||
SERVER_NAME: ":80" # FrankenPHP écoute sur le port 80
|
|
||||||
volumes:
|
|
||||||
- app_storage:/app/storage/app
|
|
||||||
- app_logs:/app/storage/logs
|
|
||||||
networks:
|
|
||||||
- proxy # réseau NPM pour être accessible depuis l'extérieur
|
|
||||||
- internal # réseau interne pour parler à PostgreSQL
|
|
||||||
depends_on:
|
|
||||||
pgsql:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
# ── Base de données PostgreSQL ──────────────────────────
|
|
||||||
pgsql:
|
|
||||||
image: postgres:17-alpine
|
|
||||||
container_name: landing-api-pgsql
|
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: "${DB_DATABASE}"
|
|
||||||
POSTGRES_USER: "${DB_USERNAME}"
|
|
||||||
POSTGRES_PASSWORD: "${DB_PASSWORD}"
|
|
||||||
PGDATA: /var/lib/postgresql/data/pgdata
|
|
||||||
volumes:
|
|
||||||
- pgsql_data:/var/lib/postgresql/data
|
|
||||||
networks:
|
networks:
|
||||||
- internal # PostgreSQL n'est PAS exposé sur le réseau proxy
|
- proxy
|
||||||
healthcheck:
|
- database
|
||||||
test: ["CMD-SHELL", "pg_isready -q -d ${DB_DATABASE} -U ${DB_USERNAME}"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
# ── Worker Laravel Queue ────────────────────────────────
|
|
||||||
queue:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: docker/Dockerfile.prod
|
|
||||||
image: landing-api:latest
|
|
||||||
container_name: landing-api-queue
|
|
||||||
restart: unless-stopped
|
|
||||||
command: ["php", "artisan", "queue:work", "--sleep=3", "--tries=3", "--max-time=3600"]
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
APP_ENV: production
|
|
||||||
APP_DEBUG: "false"
|
|
||||||
volumes:
|
volumes:
|
||||||
- app_storage:/app/storage/app
|
- storage:/var/www/html/storage
|
||||||
- app_logs:/app/storage/logs
|
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:16
|
||||||
|
container_name: landing-api-postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: ${DB_DATABASE}
|
||||||
|
POSTGRES_USER: ${DB_USERNAME}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
- internal
|
- database
|
||||||
depends_on:
|
|
||||||
pgsql:
|
|
||||||
condition: service_healthy
|
volumes:
|
||||||
|
storage:
|
||||||
|
postgres-data:
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
# Réseau externe partagé avec Nginx Proxy Manager
|
|
||||||
proxy:
|
proxy:
|
||||||
external: true
|
external: true
|
||||||
|
|
||||||
# Réseau interne isolé (app ↔ pgsql ↔ queue)
|
database:
|
||||||
internal:
|
|
||||||
driver: bridge
|
driver: bridge
|
||||||
|
|
||||||
volumes:
|
|
||||||
pgsql_data:
|
|
||||||
driver: local
|
|
||||||
app_storage:
|
|
||||||
driver: local
|
|
||||||
app_logs:
|
|
||||||
driver: local
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"php": "^8.3",
|
"php": "^8.3",
|
||||||
"filament/filament": "^5.0",
|
"filament/filament": "^5.0",
|
||||||
"laravel/framework": "^13.8",
|
"laravel/framework": "^13.8",
|
||||||
|
"laravel/octane": "^2.17",
|
||||||
"laravel/sanctum": "^4.0",
|
"laravel/sanctum": "^4.0",
|
||||||
"laravel/tinker": "^3.0"
|
"laravel/tinker": "^3.0"
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+265
-1
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "10b22fffd5baa69a8732cb3894b68663",
|
"content-hash": "5bbf65aa881d14aff56a15114641ac54",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@@ -2089,6 +2089,94 @@
|
|||||||
},
|
},
|
||||||
"time": "2026-05-28T20:35:55+00:00"
|
"time": "2026-05-28T20:35:55+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": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v13.19.0",
|
"version": "v13.19.0",
|
||||||
@@ -2313,6 +2401,95 @@
|
|||||||
},
|
},
|
||||||
"time": "2026-07-07T14:13:33+00:00"
|
"time": "2026-07-07T14:13:33+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "laravel/octane",
|
||||||
|
"version": "v2.17.5",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/laravel/octane.git",
|
||||||
|
"reference": "058ae4d7109eed40836dc42960f9388b9bf71f73"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/laravel/octane/zipball/058ae4d7109eed40836dc42960f9388b9bf71f73",
|
||||||
|
"reference": "058ae4d7109eed40836dc42960f9388b9bf71f73",
|
||||||
|
"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-06-04T09:05:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/prompts",
|
"name": "laravel/prompts",
|
||||||
"version": "v0.3.21",
|
"version": "v0.3.21",
|
||||||
@@ -7300,6 +7477,93 @@
|
|||||||
],
|
],
|
||||||
"time": "2026-05-29T05:06:50+00:00"
|
"time": "2026-05-29T05:06:50+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",
|
"name": "symfony/routing",
|
||||||
"version": "v8.1.0",
|
"version": "v8.1.0",
|
||||||
|
|||||||
@@ -0,0 +1,224 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Laravel\Octane\Contracts\OperationTerminated;
|
||||||
|
use Laravel\Octane\Events\RequestHandled;
|
||||||
|
use Laravel\Octane\Events\RequestReceived;
|
||||||
|
use Laravel\Octane\Events\RequestTerminated;
|
||||||
|
use Laravel\Octane\Events\TaskReceived;
|
||||||
|
use Laravel\Octane\Events\TaskTerminated;
|
||||||
|
use Laravel\Octane\Events\TickReceived;
|
||||||
|
use Laravel\Octane\Events\TickTerminated;
|
||||||
|
use Laravel\Octane\Events\WorkerErrorOccurred;
|
||||||
|
use Laravel\Octane\Events\WorkerStarting;
|
||||||
|
use Laravel\Octane\Events\WorkerStopping;
|
||||||
|
use Laravel\Octane\Listeners\CloseMonologHandlers;
|
||||||
|
use Laravel\Octane\Listeners\CollectGarbage;
|
||||||
|
use Laravel\Octane\Listeners\DisconnectFromDatabases;
|
||||||
|
use Laravel\Octane\Listeners\EnsureUploadedFilesAreValid;
|
||||||
|
use Laravel\Octane\Listeners\EnsureUploadedFilesCanBeMoved;
|
||||||
|
use Laravel\Octane\Listeners\FlushOnce;
|
||||||
|
use Laravel\Octane\Listeners\FlushTemporaryContainerInstances;
|
||||||
|
use Laravel\Octane\Listeners\FlushUploadedFiles;
|
||||||
|
use Laravel\Octane\Listeners\ReportException;
|
||||||
|
use Laravel\Octane\Listeners\StopWorkerIfNecessary;
|
||||||
|
use Laravel\Octane\Octane;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Octane Server
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value determines the default "server" that will be used by Octane
|
||||||
|
| when starting, restarting, or stopping your server via the CLI. You
|
||||||
|
| are free to change this to the supported server of your choosing.
|
||||||
|
|
|
||||||
|
| Supported: "roadrunner", "swoole", "frankenphp"
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'server' => env('OCTANE_SERVER', 'roadrunner'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| 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,
|
||||||
|
|
||||||
|
];
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
# ============================================================
|
|
||||||
# Dockerfile — Production (FrankenPHP)
|
|
||||||
# FrankenPHP = serveur web + PHP runtime tout-en-un
|
|
||||||
# Remplace PHP-FPM + Nginx en un seul container
|
|
||||||
# ============================================================
|
|
||||||
|
|
||||||
FROM dunglas/frankenphp:php8.3-alpine AS base
|
|
||||||
|
|
||||||
# Extensions PHP nécessaires pour Laravel
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
postgresql-dev \
|
|
||||||
libpng-dev \
|
|
||||||
libjpeg-turbo-dev \
|
|
||||||
freetype-dev \
|
|
||||||
libzip-dev \
|
|
||||||
oniguruma-dev \
|
|
||||||
icu-dev \
|
|
||||||
curl \
|
|
||||||
unzip \
|
|
||||||
git \
|
|
||||||
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
|
|
||||||
&& docker-php-ext-install \
|
|
||||||
pdo \
|
|
||||||
pdo_pgsql \
|
|
||||||
pgsql \
|
|
||||||
mbstring \
|
|
||||||
zip \
|
|
||||||
gd \
|
|
||||||
bcmath \
|
|
||||||
intl \
|
|
||||||
opcache \
|
|
||||||
pcntl
|
|
||||||
|
|
||||||
# Composer
|
|
||||||
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
|
|
||||||
|
|
||||||
# ── Stage Build (Node pour compiler les assets Vite) ────────
|
|
||||||
FROM base AS builder
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Dépendances PHP (sans dev)
|
|
||||||
COPY composer.json composer.lock ./
|
|
||||||
RUN composer install \
|
|
||||||
--no-interaction \
|
|
||||||
--no-dev \
|
|
||||||
--prefer-dist \
|
|
||||||
--optimize-autoloader \
|
|
||||||
--no-scripts
|
|
||||||
|
|
||||||
# Dépendances Node + build assets
|
|
||||||
COPY package.json package-lock.json* ./
|
|
||||||
RUN apk add --no-cache nodejs npm \
|
|
||||||
&& npm ci --ignore-scripts
|
|
||||||
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Génère les assets Vite
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
# Post-scripts Composer
|
|
||||||
RUN composer run-script post-autoload-dump || true
|
|
||||||
|
|
||||||
# ── Stage Final ──────────────────────────────────────────────
|
|
||||||
FROM base AS production
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Copie tout depuis le builder
|
|
||||||
COPY --from=builder /app /app
|
|
||||||
|
|
||||||
# Config PHP optimisée prod
|
|
||||||
COPY docker/php.prod.ini /usr/local/etc/php/conf.d/99-prod.ini
|
|
||||||
|
|
||||||
# Permissions sur storage et bootstrap/cache
|
|
||||||
RUN mkdir -p storage/logs storage/framework/cache storage/framework/sessions storage/framework/views bootstrap/cache \
|
|
||||||
&& chown -R www-data:www-data storage bootstrap/cache \
|
|
||||||
&& chmod -R 775 storage bootstrap/cache
|
|
||||||
|
|
||||||
# FrankenPHP écoute sur le port 80
|
|
||||||
EXPOSE 80
|
|
||||||
|
|
||||||
# FrankenPHP sert le dossier public/ de Laravel
|
|
||||||
CMD ["frankenphp", "php-server", "--root", "/app/public"]
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name _;
|
|
||||||
root /var/www/html/public;
|
|
||||||
index index.php;
|
|
||||||
|
|
||||||
# Sécurité — masque la version Nginx
|
|
||||||
server_tokens off;
|
|
||||||
|
|
||||||
# Taille max des uploads
|
|
||||||
client_max_body_size 50M;
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
access_log /var/log/nginx/access.log;
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
|
|
||||||
# Gzip
|
|
||||||
gzip on;
|
|
||||||
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
|
|
||||||
gzip_min_length 256;
|
|
||||||
|
|
||||||
# Assets statiques — cache long terme
|
|
||||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|webp)$ {
|
|
||||||
expires 1y;
|
|
||||||
add_header Cache-Control "public, immutable";
|
|
||||||
try_files $uri =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Route principale Laravel
|
|
||||||
location / {
|
|
||||||
try_files $uri $uri/ /index.php?$query_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
# PHP-FPM
|
|
||||||
location ~ \.php$ {
|
|
||||||
fastcgi_pass app:9000;
|
|
||||||
fastcgi_index index.php;
|
|
||||||
fastcgi_buffers 16 16k;
|
|
||||||
fastcgi_buffer_size 32k;
|
|
||||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
|
||||||
include fastcgi_params;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Bloque l'accès aux fichiers cachés
|
|
||||||
location ~ /\. {
|
|
||||||
deny all;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
; Configuration PHP optimisée pour la production
|
|
||||||
|
|
||||||
[PHP]
|
|
||||||
; Sécurité
|
|
||||||
expose_php = Off
|
|
||||||
display_errors = Off
|
|
||||||
display_startup_errors = Off
|
|
||||||
log_errors = On
|
|
||||||
error_log = /var/www/html/storage/logs/php-errors.log
|
|
||||||
|
|
||||||
; Performance
|
|
||||||
memory_limit = 256M
|
|
||||||
max_execution_time = 60
|
|
||||||
max_input_time = 60
|
|
||||||
post_max_size = 50M
|
|
||||||
upload_max_filesize = 50M
|
|
||||||
|
|
||||||
; OPcache
|
|
||||||
opcache.enable = 1
|
|
||||||
opcache.enable_cli = 0
|
|
||||||
opcache.memory_consumption = 128
|
|
||||||
opcache.interned_strings_buffer = 16
|
|
||||||
opcache.max_accelerated_files = 10000
|
|
||||||
opcache.revalidate_freq = 0
|
|
||||||
opcache.validate_timestamps = 0
|
|
||||||
opcache.save_comments = 1
|
|
||||||
opcache.fast_shutdown = 1
|
|
||||||
Reference in New Issue
Block a user