انتقل إلى المحتوى الرئيسي

الفصل 4: النشر السحابي

مقدمة​

تطبيقك جاهز، تم تكوين Docker، وتم إعداد CI/CD. حان الوقت لوضعه على الإنترنت! يغطي هذا الفصل الخيارات الرئيسية للنشر السحابي.


🎯 أهداف الفصل​

في نهاية هذا الفصل، ستعرف:

  1. ✅ النشر على Railway
  2. ✅ النشر على Heroku
  3. ✅ فهم خيارات AWS
  4. ✅ تكوين قاعدة بيانات مُدارة
  5. ✅ اختيار المنصة المناسبة

1. مقارنة المنصات​

المنصةالصعوبةالتكلفةمثالي لـ
Railway⭐ سهلمجاني → $5/شهرمشاريع شخصية، شركات ناشئة
Heroku⭐ سهل$7/شهرتطبيقات بسيطة
Render⭐ سهلمجاني → $7/شهربديل Heroku
AWS ECS⭐⭐⭐ معقدمتغيرالشركات
Kubernetes⭐⭐⭐⭐ متقدممتغيرالخدمات المصغرة

2. Railway (موصى به للمبتدئين)​

لماذا Railway؟​

  • ✅ واجهة بسيطة
  • ✅ النشر من GitHub
  • ✅ PostgreSQL مدمج
  • ✅ مجاني للبدء
  • ✅ يدعم Docker

النشر​

الخيار 1: من GitHub

  1. اذهب إلى railway.app
  2. "New Project" → "Deploy from GitHub repo"
  3. اختر المستودع الخاص بك
  4. يكتشف Railway تلقائيًا Spring Boot

الخيار 2: مع Docker

# تثبيت Railway CLI
npm i -g @railway/cli

# تسجيل الدخول
railway login

# إنشاء مشروع
railway init

# النشر
railway up

التكوين​

# متغيرات البيئة (في لوحة تحكم Railway)
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=${{Postgres.DATABASE_URL}}

إضافة PostgreSQL​

  1. في مشروع Railway: "New" → "Database" → "PostgreSQL"
  2. يتم حقن المتغيرات تلقائيًا

railway.json​

{
"$schema": "https://railway.app/railway.schema.json",
"build": {
"builder": "DOCKERFILE",
"dockerfilePath": "Dockerfile"
},
"deploy": {
"startCommand": "java -jar app.jar",
"healthcheckPath": "/actuator/health",
"restartPolicyType": "ON_FAILURE"
}
}

3. Heroku​

التحضير​

Procfile (في الجذر):

web: java -Dserver.port=$PORT -jar target/*.jar

system.properties:

java.runtime.version=17

النشر​

# تثبيت Heroku CLI
# https://devcenter.heroku.com/articles/heroku-cli

# تسجيل الدخول
heroku login

# إنشاء التطبيق
heroku create my-spring-app

# إضافة PostgreSQL
heroku addons:create heroku-postgresql:mini

# النشر
git push heroku main

# عرض السجلات
heroku logs --tail

متغيرات البيئة​

heroku config:set SPRING_PROFILES_ACTIVE=prod
heroku config:set JWT_SECRET=your-secret-key

# عرض جميع المتغيرات
heroku config

مع Docker​

# تسجيل الدخول إلى سجل Heroku
heroku container:login

# البناء والدفع
heroku container:push web

# النشر
heroku container:release web

4. Render​

النشر​

  1. اذهب إلى render.com
  2. "New" → "Web Service"
  3. ربط GitHub
  4. التكوين:
    • Build Command: mvn clean package -DskipTests
    • Start Command: java -jar target/*.jar

render.yaml​

services:
- type: web
name: my-spring-app
env: docker
dockerfilePath: ./Dockerfile
envVars:
- key: SPRING_PROFILES_ACTIVE
value: prod
- key: DATABASE_URL
fromDatabase:
name: mydb
property: connectionString

databases:
- name: mydb
plan: free

5. AWS (خيارات)​

Elastic Beanstalk (بسيط)​

# تثبيت EB CLI
pip install awsebcli

# التهيئة
eb init

# إنشاء البيئة
eb create production

# النشر
eb deploy

ECS مع Fargate (Docker)​

# إنشاء مجموعة
aws ecs create-cluster --cluster-name my-cluster

# إنشاء تعريف المهمة (JSON)
aws ecs register-task-definition --cli-input-json file://task-definition.json

# إنشاء خدمة
aws ecs create-service \
--cluster my-cluster \
--service-name my-service \
--task-definition my-task \
--desired-count 2

task-definition.json​

{
"family": "my-spring-app",
"containerDefinitions": [
{
"name": "app",
"image": "myuser/myapp:latest",
"portMappings": [
{
"containerPort": 8080,
"hostPort": 8080
}
],
"environment": [
{
"name": "SPRING_PROFILES_ACTIVE",
"value": "prod"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/my-app",
"awslogs-region": "us-east-1"
}
}
}
],
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512"
}

6. قاعدة بيانات مُدارة​

Railway PostgreSQL​

# تم تكوينه تلقائيًا
spring.datasource.url=${DATABASE_URL}

Heroku Postgres​

# يوفر Heroku DATABASE_URL تلقائيًا
spring.datasource.url=${DATABASE_URL}

AWS RDS​

spring.datasource.url=jdbc:postgresql://mydb.xxx.us-east-1.rds.amazonaws.com:5432/mydb
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}

تحليل DATABASE_URL​

بعض المنصات توفر URL بالتنسيق:

postgres://user:password@host:5432/dbname

تكوين Spring للتحليل:

@Configuration
public class DatabaseConfig {

@Bean
@Profile("prod")
public DataSource dataSource() {
String databaseUrl = System.getenv("DATABASE_URL");

if (databaseUrl != null && databaseUrl.startsWith("postgres://")) {
// تحليل تنسيق Heroku/Railway
URI uri = URI.create(databaseUrl);
String username = uri.getUserInfo().split(":")[0];
String password = uri.getUserInfo().split(":")[1];
String jdbcUrl = "jdbc:postgresql://" + uri.getHost() + ":" + uri.getPort() + uri.getPath();

HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl(jdbcUrl);
ds.setUsername(username);
ds.setPassword(password);
return ds;
}

// بديل
return DataSourceBuilder.create().build();
}
}

7. قائمة التحقق من النشر​

قبل النشر​

□ الاختبارات تمر محليًا
□ تكوين ملف الإنتاج
□ الأسرار خارجية
□ تم اختبار Dockerfile
□ تم تكوين فحص الصحة
□ تم تكوين السجلات

متغيرات البيئة​

# أساسية
SPRING_PROFILES_ACTIVE=prod
DATABASE_URL=...
JWT_SECRET=...

# اختيارية
SERVER_PORT=8080
JAVA_OPTS="-Xmx512m"

بعد النشر​

□ التطبيق متاح
□ فحص الصحة OK
□ السجلات مرئية
□ قاعدة البيانات متصلة
□ المراقبة في مكانها

8. المراقبة في الإنتاج​

Actuator​

management.endpoints.web.exposure.include=health,info,prometheus
management.endpoint.health.show-details=when_authorized

تسجيل السحابة​

# سجلات JSON للسحابة
logging.pattern.console={"timestamp":"%d","level":"%p","logger":"%c","message":"%m"}%n

خدمات المراقبة​

  • Railway: مقاييس مدمجة
  • Heroku: مقاييس Heroku
  • AWS: CloudWatch
  • خارجية: Datadog, New Relic

9. ملخص​

توصيات حسب حالة الاستخدام​

مشروع شخصي / POC:
→ Railway (مجاني، بسيط)

شركة ناشئة / MVP:
→ Railway أو Render ($5-20/شهر)

شركة صغيرة / إنتاج:
→ Heroku أو AWS Elastic Beanstalk

شركة كبيرة / توسع:
→ AWS ECS / Kubernetes

النشر السريع (Railway)​

# 1. امتلاك Dockerfile
# 2. الدفع على GitHub
# 3. على railway.app:
# - مشروع جديد → GitHub
# - إضافة PostgreSQL
# - تكوين المتغيرات
# 4. تم! 🚀

🎯 الخطوة التالية​

حان وقت الممارسة! دعونا نقوم بتدوير ونشر تطبيق.

➡️ TP12.1: التدوير الكامل


⬅️ العودة إلى الوحدة 12