255 lines
10 KiB
YAML
255 lines
10 KiB
YAML
# ============================================================
|
||
# سيرو في حاويات — نسخة واحدة كاملة على سيرفر واحد
|
||
# ============================================================
|
||
# المبدأ: التقسيم بالدور (nginx / fpm / سوكيتات / mysql / redis)
|
||
# لا حاوية-واحدة-فيها-كل-شيء، ولا تفتيت microservices.
|
||
# الأداء = نفس العمليات على نفس النواة؛ الفرق تشغيلي فقط.
|
||
#
|
||
# التشغيل: docker compose up -d --build (انظر README.md)
|
||
# ============================================================
|
||
|
||
name: siro
|
||
|
||
services:
|
||
nginx:
|
||
image: nginx:1.27-alpine
|
||
ports:
|
||
- "${HTTP_PORT:-8080}:80"
|
||
volumes:
|
||
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||
- ../backend:/var/www/backend:ro
|
||
- ../payment_server/v2:/var/www/v2:ro
|
||
- ../loction_server:/var/www/loction_server:ro
|
||
- ../dashboard:/var/www/dashboard:ro
|
||
depends_on:
|
||
- php
|
||
- php_transit
|
||
- php_food
|
||
mem_limit: 256m
|
||
restart: unless-stopped
|
||
|
||
# php-fpm واحدة تخدم كل الخدمات الطلبية (backend + payment v2)
|
||
# التقسيم لأبعد من هذا لا يضيف أداءً — نفس الصورة، نفس النواة.
|
||
php:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/php/Dockerfile.fpm
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
volumes:
|
||
- ../backend:/var/www/backend
|
||
- ../payment_server/v2:/var/www/v2
|
||
- ../loction_server:/var/www/loction_server
|
||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||
- ./php/www-pool.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
depends_on:
|
||
- mysql
|
||
- redis
|
||
mem_limit: 2g
|
||
restart: unless-stopped
|
||
|
||
# php-fpm معزولة لخدمة Mawasalati (transit) — حاوية مستقلة عن الباك إند الرئيسي.
|
||
# المشترك الوحيد مع النظام الأساسي: JWT ومصادقة السائق/الراكب عبر backend/core
|
||
# (نُركّبها read-only)، ونفس mysql/redis. لا صلة بـ backend الرئيسي ولا payment v2،
|
||
# ولا تتأثر Mawasalati إذا امتلأ pool الباك إند الرئيسي أو انهار.
|
||
php_transit:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/php/Dockerfile.fpm.transit
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
volumes:
|
||
- ../backend/core:/var/www/backend/core:ro
|
||
- ../backend/functions.php:/var/www/backend/functions.php:ro
|
||
# نفس سبب php_food: JwtService يحتاج Firebase\JWT من backend/vendor،
|
||
# والصورة بلا composer. للقراءة فقط.
|
||
- ../backend/vendor:/var/www/backend/vendor:ro
|
||
- ../backend/transit:/var/www/backend/transit
|
||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||
- ./php/www-pool.transit.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
depends_on:
|
||
- mysql
|
||
- redis
|
||
mem_limit: 512m
|
||
restart: unless-stopped
|
||
|
||
# php-fpm معزولة لوحدة طلبات الطعام — نفس منطق عزل php_transit.
|
||
# المشترك الوحيد: JWT (backend/core) ونفس mysql/redis. قاعدة siro_food منفصلة.
|
||
php_food:
|
||
build:
|
||
context: ..
|
||
dockerfile: docker/php/Dockerfile.fpm.transit
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
volumes:
|
||
- ../backend/core:/var/www/backend/core:ro
|
||
- ../backend/functions.php:/var/www/backend/functions.php:ro
|
||
# core/bootstrap.php يحمّل backend/vendor/autoload.php، و JwtService
|
||
# يحتاج Firebase\JWT. الصورة هنا بلا composer عمداً، ودون هذا التركيب
|
||
# كانت كل نقطة طعام تسقط بـ Class "Firebase\JWT\JWT" not found.
|
||
# للقراءة فقط: مكتبات مشتركة لا كود مشترك — العزل باقٍ.
|
||
- ../backend/vendor:/var/www/backend/vendor:ro
|
||
- ../backend/food:/var/www/backend/food
|
||
- ./php/opcache.ini:/usr/local/etc/php/conf.d/zz-opcache.ini:ro
|
||
- ./php/food-pool.conf:/usr/local/etc/php-fpm.d/zz-pool.conf:ro
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
depends_on:
|
||
- mysql
|
||
- redis
|
||
mem_limit: 768m
|
||
restart: unless-stopped
|
||
|
||
# سوكيت الطعام — WS بورت 4040 + HTTP داخلي 4041
|
||
socket_food:
|
||
build:
|
||
context: ./php
|
||
dockerfile: Dockerfile.socket
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
command: ["php", "food_socket.php", "start"]
|
||
working_dir: /app
|
||
volumes:
|
||
- ../food_server:/app
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
ports:
|
||
# نفس منطق سوكيت السائقين: لا نفتح 4040 للعالم مباشرة — nginx على
|
||
# المضيف يستمع 4040 بالشهادة ويمرّر إلى 14040 هنا. 4041 داخلي فقط
|
||
# (الباك إند يناديه عبر http://socket_food:4041).
|
||
- "127.0.0.1:${FOOD_SOCKET_PORT:-14040}:4040"
|
||
depends_on:
|
||
- redis
|
||
mem_limit: 512m
|
||
restart: unless-stopped
|
||
|
||
# سوكيت السائقين (Workerman + PHPSocketIO) — WS بورت 2020 + HTTP داخلي 2021
|
||
# عملية دائمة، لا علاقة لها بـ fpm — حاوية مستقلة إجبارياً.
|
||
socket_driver:
|
||
build:
|
||
context: ./php
|
||
dockerfile: Dockerfile.socket
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
command: ["php", "driver_socket.php", "start"]
|
||
working_dir: /app
|
||
volumes:
|
||
- ../loction_server:/app
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
ports:
|
||
# لا نفتح 2020 للعالم مباشرة: Workerman يتكلم نصاً صريحاً، والتطبيق يطلب
|
||
# TLS على هذا المنفذ (https://…:2020) فتتجمّد المصافحة وينتهي بـ timeout.
|
||
# nginx على المضيف يستمع على 2020 بالشهادة ويمرّر إلى 12020 هنا.
|
||
# انظر nginx/siro-sockets-tls.conf
|
||
# المنفذ قابل للضبط: على سيرفر تعمل عليه أكثر من نسخة (siro/tripz/intaleq)
|
||
# يتصادم 12020 الثابت فلا تبدأ الحاوية أصلاً. اضبط DRIVER_SOCKET_PORT في .env.
|
||
- "127.0.0.1:${DRIVER_SOCKET_PORT:-12020}:2020"
|
||
# و2021 داخلي فقط: الباك إند يناديه عبر http://socket_driver:2021
|
||
depends_on:
|
||
- redis
|
||
mem_limit: 768m
|
||
restart: unless-stopped
|
||
|
||
# سوكيت الركاب (ride_server) — WS بورت 3030 + HTTP داخلي 3031
|
||
socket_passenger:
|
||
build:
|
||
context: ./php
|
||
dockerfile: Dockerfile.socket
|
||
args:
|
||
PHP_VERSION: "${PHP_VERSION:-8.2}"
|
||
command: ["php", "passenger_socket.php", "start"]
|
||
working_dir: /app
|
||
volumes:
|
||
- ../ride_server:/app
|
||
- ./keys:/keys:ro
|
||
env_file: .env
|
||
ports:
|
||
# نفس منطق سوكيت السائقين: nginx على المضيف يستمع على 3030 بالشهادة
|
||
# ويمرّر إلى 13030 هنا. و3031 داخلي فقط (http://socket_passenger:3031).
|
||
- "127.0.0.1:${PASSENGER_SOCKET_PORT:-13030}:3030"
|
||
depends_on:
|
||
- redis
|
||
mem_limit: 512m
|
||
restart: unless-stopped
|
||
|
||
mysql:
|
||
image: mysql:8.4
|
||
environment:
|
||
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD:?set in .env}"
|
||
# بيانات القاعدة على volume مسمّى — يتجاوز overlayfs = أداء قرص شبه أصلي.
|
||
volumes:
|
||
- mysql-data:/var/lib/mysql
|
||
- ./mysql/init:/docker-entrypoint-initdb.d:ro
|
||
command:
|
||
- --innodb-buffer-pool-size=1G
|
||
- --max-connections=300
|
||
- --innodb-flush-log-at-trx-commit=1
|
||
- --slow-query-log=1
|
||
- --long-query-time=0.2
|
||
- --slow-query-log-file=/var/lib/mysql/slow.log
|
||
ports:
|
||
# للإدارة من السيرفر نفسه فقط — ليس للعامة.
|
||
# 33061 يحتجزه مشروع آخر على السيرفر نفسه (intaleq-mysql-1)، و33063
|
||
# يحتجزه tripz-core-mysql-1. كان المنفذ هنا 33061 بينما الحاوية تعمل
|
||
# فعلياً على 33062 (تعديل يدوي وقت الإقلاع لم يُنقل إلى الملف)، فلمّا
|
||
# أعاد compose الإنشاء فرض قيمة الملف وفشل الربط وسقطت القاعدة.
|
||
- "127.0.0.1:33062:3306"
|
||
mem_limit: 2560m
|
||
restart: unless-stopped
|
||
|
||
phpmyadmin:
|
||
image: phpmyadmin/phpmyadmin
|
||
environment:
|
||
PMA_HOST: mysql
|
||
PMA_PORT: 3306
|
||
UPLOAD_LIMIT: 300M
|
||
ports:
|
||
- "8082:80" # ادخل عليه عبر http://your-domain:8082 أو افتح بورت 8082 في CloudPanel
|
||
depends_on:
|
||
- mysql
|
||
mem_limit: 256m
|
||
restart: unless-stopped
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
command:
|
||
- redis-server
|
||
- --maxmemory
|
||
- 400mb
|
||
- --maxmemory-policy
|
||
- noeviction
|
||
- --appendonly
|
||
- "yes"
|
||
volumes:
|
||
- redis-data:/data
|
||
mem_limit: 512m
|
||
restart: unless-stopped
|
||
|
||
# خادم TURN لمكالمات الصوت (رحلات + توصيل الطعام).
|
||
# network_mode: host إجباري هنا لا تفضيلاً: coturn يضع عنوان الخادم داخل
|
||
# حمولة ICE، ولو مرّ عبر جسر دوكر لأعلن عنواناً داخلياً (172.x) فيفشل
|
||
# التمرير. ومع host يسري جدار الحماية عادةً بدل أن يلتفّ عليه docker-proxy.
|
||
coturn:
|
||
image: coturn/coturn:4.6-alpine
|
||
network_mode: host
|
||
volumes:
|
||
- ./coturn/turnserver.conf:/etc/coturn/turnserver.conf:ro
|
||
command: >
|
||
-c /etc/coturn/turnserver.conf
|
||
--realm=${TURN_REALM:-siromove.com}
|
||
--static-auth-secret=${TURN_STATIC_AUTH_SECRET:?TURN_STATIC_AUTH_SECRET is required}
|
||
--external-ip=${TURN_EXTERNAL_IP:?TURN_EXTERNAL_IP is required}
|
||
--listening-ip=${TURN_EXTERNAL_IP}
|
||
--relay-ip=${TURN_EXTERNAL_IP}
|
||
mem_limit: 256m
|
||
restart: unless-stopped
|
||
|
||
volumes:
|
||
mysql-data:
|
||
redis-data:
|