1. نظرة عامة
يوضّح هذا الدرس التطبيقي الميزات والإمكانات المصمَّمة لتبسيط سير عمل التطوير لمهندسي البرامج المكلّفين بتطوير تطبيقات NodeJS في بيئة مُضمَّنة في حاوية. يتطلّب تطوير الحاويات المعتاد أن يفهم المستخدم تفاصيل الحاويات وعملية التصميم. بالإضافة إلى ذلك، على المطوّرين عادةً إيقاف عملية التطوير مؤقتًا والانتقال من بيئة التطوير المتكاملة (IDE) لاختبار تطبيقاتهم وتصحيح الأخطاء فيها في بيئات بعيدة. باستخدام الأدوات والتكنولوجيات المذكورة في هذا البرنامج التعليمي، يمكن للمطوّرين العمل بفعالية مع التطبيقات المستندة إلى حاويات بدون مغادرة بيئة التطوير المتكاملة.
ما ستتعلمه
في هذا الدرس التطبيقي، ستتعرّف على طرق التطوير باستخدام الحاويات في Google Cloud Platform، بما في ذلك:
- إنشاء تطبيق Nodejs مبتدئ
- إعداد تطبيق Nodejs لتطوير الحاويات
- كتابة رمز لخدمة REST بسيطة لإنشاء وقراءة وتعديل وحذف البيانات
- النشر على GKE
- تصحيح حالة الخطأ
- استخدام نقاط الإيقاف / السجلات
- إعادة نشر التغييرات على GKE
- اختياري: دمج CloudSQL لتوفير ثبات الواجهة الخلفية
2. الإعداد والمتطلبات
إعداد البيئة بوتيرة ذاتية
- سجِّل الدخول إلى Google Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.



- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة من الأحرف لا تستخدمها Google APIs، ويمكنك تعديلها في أي وقت.
- يجب أن يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud، كما أنّه غير قابل للتغيير (لا يمكن تغييره بعد ضبطه). تنشئ Cloud Console تلقائيًا سلسلة فريدة، ولا يهمّك عادةً ما هي. في معظم دروس الترميز، عليك الرجوع إلى رقم تعريف المشروع (ويتم تحديده عادةً على أنّه
PROJECT_ID)، لذا إذا لم يعجبك، يمكنك إنشاء رقم آخر عشوائي، أو يمكنك تجربة رقمك الخاص ومعرفة ما إذا كان متاحًا. ثم يتم "تجميده" بعد إنشاء المشروع. - هناك قيمة ثالثة، وهي رقم المشروع الذي تستخدمه بعض واجهات برمجة التطبيقات. يمكنك الاطّلاع على مزيد من المعلومات عن كل هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console من أجل استخدام موارد/واجهات برمجة تطبيقات Cloud. لن تكلفك تجربة هذا الدرس البرمجي الكثير من المال، إن لم تكلفك شيئًا على الإطلاق. لإيقاف الموارد كي لا يتم تحصيل رسوم منك بعد هذا الدرس التطبيقي حول الترميز، اتّبِع أي تعليمات "تنظيف" واردة في نهاية الدرس. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
بدء Cloudshell Editor
تم تصميم هذا الدرس التطبيقي واختباره لاستخدامه مع "محرّر Google Cloud Shell". للوصول إلى المحرِّر، اتّبِع الخطوات التالية:
- الوصول إلى مشروعك على Google من خلال https://console.cloud.google.com
- في أعلى يسار الصفحة، انقر على رمز محرر Cloud Shell

- سيتم فتح لوحة جديدة في أسفل النافذة
- انقر على الزر "فتح المحرِّر"

- سيتم فتح المحرِّر مع مستكشف على اليسار ومحرِّر في المنطقة الوسطى
- يجب أن يتوفّر جزء وحدة طرفية أيضًا في أسفل الشاشة
- إذا لم تكن النافذة الطرفية مفتوحة، استخدِم مجموعة المفاتيح `ctrl+`` لفتح نافذة طرفية جديدة.
إعداد gcloud
في Cloud Shell، اضبط رقم تعريف مشروعك والمنطقة التي تريد نشر تطبيقك فيها. احفظها كمتغيرات PROJECT_ID وREGION.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
إعداد مجموعة GKE وقاعدة البيانات
- نزِّل نص الإعداد البرمجي واجعله قابلاً للتنفيذ.
wget https://raw.githubusercontent.com/GoogleCloudPlatform/container-developer-workshop/main/labs/nodejs/setup.sh
chmod +x setup.sh
توفير البنية الأساسية المستخدَمة في هذا الدرس التطبيقي
في هذا التمرين العملي، ستنفّذ رمزًا برمجيًا على GKE وتصل إلى البيانات المخزّنة في قاعدة بيانات Spanner. يُعدّ برنامج الإعداد النصي أدناه هذه البنية الأساسية لك.
- افتح ملف
setup.shوعدِّل قيم كلمات المرور التي تم ضبطها حاليًا على CHANGEME - تشغيل نص الإعداد لإنشاء مجموعة GKE وقاعدة بيانات CloudSQL التي ستستخدمها في هذا التمرين العملي
./setup.sh
- في Cloud Shell، أنشئ دليلاً جديدًا بالاسم
mynodejsapp
mkdir mynodejsapp
- انتقِل إلى هذا الدليل وافتحه كمساحة عمل. سيؤدي ذلك إلى إعادة تحميل المحرّر من خلال إنشاء إعدادات مساحة العمل في المجلد الذي تم إنشاؤه حديثًا.
cd mynodejsapp && cloudshell workspace .
- ثبِّت Node وNPM باستخدام NVM.
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
# This loads nvm bash_completion
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
nvm install stable
nvm alias default stable
3- إنشاء تطبيق جديد للمبتدئين
- إعداد التطبيق
إنشاء ملف package.json من خلال تنفيذ الأمر التالي
npm init
Choose the entry point: (index.js) src/index.js and default values for the rest of the parameters. This will create the file with following contents
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
- إضافة نقطة دخول
عدِّل هذا الملف لتضمين أمر البدء في النص البرمجي "start": "node src/index.js",. بعد إجراء التغيير، من المفترض أن تبدو النصوص البرمجية مثل مقتطف الرمز البرمجي أدناه:
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
- إضافة Express Dependency
سيستخدم الرمز الذي سنضيفه أيضًا express، لذا دعنا نضيف هذه التبعية إلى ملف package.json هذا. بعد إجراء كل التغييرات، يجب أن يكون الملف package.json كما هو موضّح أدناه.
{
"name": "mynodejsapp",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Your Name",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}
- إنشاء ملف index.js
أنشئ دليل ملفات المصدر باسم src
أنشئ الملف src/index.js باستخدام الرمز التالي
const express = require('express');
const app = express();
const PORT = 8080;
app.get('/', (req, res) => {
var message="Greetings from Node";
res.send({ message: message });
});
app.listen(PORT, () => {
console.log(`Server running at: http://localhost:${PORT}/`);
});
لاحظ أنّه تم ضبط رقم المنفذ على القيمة 8080
إنشاء بيانات
توفّر Skaffold أدوات متكاملة لتسهيل تطوير الحاويات. في هذه الخطوة، ستُهيّئ skaffold التي ستنشئ تلقائيًا ملفات YAML الأساسية في Kubernetes. نفِّذ الأمر أدناه لبدء العملية.
نفِّذ الأمر التالي في الوحدة الطرفية
skaffold init --generate-manifests
عندما يُطلب منك ذلك:
- أدخِل 8080 للمنفذ
- أدخِل y لحفظ الإعدادات
تمت إضافة ملفَين إلى مساحة العمل، وهما skaffold.yaml وdeployment.yaml
تعديل اسم التطبيق
لا تتطابق القيم التلقائية المُضمَّنة في الإعداد حاليًا مع اسم تطبيقك. عدِّل الملفات للإشارة إلى اسم تطبيقك بدلاً من القيم التلقائية.
- تغيير الإدخالات في ملف إعدادات Skaffold
- فتح "
skaffold.yaml" - اختَر اسم الصورة المضبوطة حاليًا على
package-json-image - انقر بزر الماوس الأيمن واختَر "تغيير كل التكرارات"
- اكتب الاسم الجديد باللغة
mynodejsapp
- تغيير الإدخالات في إعدادات Kubernetes
- فتح ملف
deployment.yaml - اختَر اسم الصورة المضبوطة حاليًا على
package-json-image - انقر بزر الماوس الأيمن واختَر "تغيير كل التكرارات"
- اكتب الاسم الجديد باللغة
mynodejsapp
يُرجى العِلم أنّه في ملف skaffold.yaml، يستخدم القسم build buildpacks لتضمين التطبيق. لا يحتوي هذا الرمز على Dockerfile ولا يحتاج المطوّر إلى أي معرفة بـ Docker لتضمين هذا التطبيق.
بالإضافة إلى ذلك، يتم تفعيل المزامنة السريعة تلقائيًا بين المحرّر والحاوية قيد التشغيل من خلال إعداد Skaffold هذا. لا يلزم إجراء أي إعدادات إضافية لتفعيل المزامنة السريعة.
4. التعرّف على عملية التطوير
في هذا القسم، ستتّبع بضع خطوات باستخدام مكوّن Cloud Code الإضافي للتعرّف على العمليات الأساسية والتأكّد من صحة إعدادات تطبيقك الأوّلي.
يتكامل Cloud Code مع Skaffold لتبسيط عملية التطوير. عند النشر إلى GKE في الخطوات التالية، ستنشئ Cloud Code وSkaffold تلقائيًا صورة الحاوية، وتدفعها إلى Container Registry، ثم تنشر تطبيقك إلى GKE. يحدث ذلك وراء الكواليس، حيث يتم تجريد التفاصيل بعيدًا عن مسار المطوّر. تعمل Cloud Code أيضًا على تحسين عملية التطوير من خلال توفير إمكانات تصحيح الأخطاء والمزامنة السريعة التقليدية للتطوير المستند إلى الحاويات.
النشر على Kubernetes
- في اللوحة أسفل "محرّر Cloud Shell"، انقر على Cloud Code 

- في اللوحة التي تظهر في أعلى الصفحة، اختَر التشغيل على Kubernetes. إذا طُلب منك ذلك، اختَر "نعم" لاستخدام سياق Kubernetes الحالي.

- في المرة الأولى التي تنفّذ فيها الأمر، سيظهر طلب في أعلى الشاشة يسألك عمّا إذا كنت تريد سياق Kubernetes الحالي، اختَر "نعم" للقبول واستخدام السياق الحالي.

- بعد ذلك، ستظهر رسالة تطلب منك تحديد سجلّ الحاويات الذي تريد استخدامه. اضغط على مفتاح Enter لقبول القيمة التلقائية المقدَّمة

- انقر على علامة التبويب "الإخراج" (Output) في اللوحة السفلية للاطّلاع على مستوى التقدّم والإشعارات

- اختَر "Kubernetes: Run/Debug - Detailed" (Kubernetes: تشغيل/تصحيح الأخطاء - تفصيلي) في القائمة المنسدلة للقناة على اليسار لعرض تفاصيل إضافية وسجلات يتم بثها مباشرةً من الحاويات.

- يمكنك الرجوع إلى العرض المبسَّط من خلال اختيار "Kubernetes: تشغيل/تصحيح الأخطاء" من القائمة المنسدلة.
- عند اكتمال عملية الإنشاء والاختبارات، ستظهر الرسالة
Resource deployment/mynodejsapp status completed successfullyفي علامة التبويب "الإخراج"، وسيتم إدراج عنوان URL: "Forwarded URL from service demo-app: http://localhost:8080" - في نافذة Cloud Code الطرفية، مرِّر مؤشر الماوس فوق عنوان URL في الناتج (http://localhost:8080)، ثم انقر على "فتح معاينة الويب" (Open Web Preview) في نصيحة الأداة التي تظهر.
سيكون الردّ:
{"message":"Greetings from Node"}
إعادة التحميل السريع
- الانتقال إلى
src/index.jsتعديل رمز رسالة الترحيب إلى'Hello from Node'
لاحظ على الفور أنّه في نافذة Output، في طريقة العرض Kubernetes: Run/Debug، يزامن برنامج المراقبة الملفات المعدَّلة مع الحاوية في Kubernetes.
Update initiated File sync started for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a File sync succeeded for 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Update succeeded
- إذا انتقلت إلى طريقة العرض
Kubernetes: Run/Debug - Detailed، ستلاحظ أنّها تتعرّف على تغييرات الملف وتعيد تشغيل العقدة.
files modified: [src/index.js] Copying files:map[src/index.js:[/workspace/src/index.js]]togcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Syncing 1 files for gcr.io/myproject/mynodejsapp:latest@sha256:f554756b3b4d6c301c4b26ef96102227cfa2833270db56241248ae42baa1971a Watching for changes... [mynodejsapp] [mynodejsapp]> mynodejsapp@1.0.0 start /workspace [mynodejsapp]> node src/index.js [mynodejsapp] [mynodejsapp]Server running at: http://localhost:8080/
- يُرجى إعادة تحميل المتصفّح للاطّلاع على النتائج المعدَّلة.
تصحيح الأخطاء
- انتقِل إلى "عرض تصحيح الأخطاء" وأوقِف سلسلة المحادثات الحالية
. - انقر على
Cloud Codeفي القائمة السفلية، ثم اختَرDebug on Kubernetesلتشغيل التطبيق في وضعdebug.
- في طريقة العرض
Kubernetes Run/Debug - DetailedلنافذةOutput، لاحظ أنّ Skaffold سينشر هذا التطبيق في وضع تصحيح الأخطاء. - سيستغرق إنشاء التطبيق ونشره بضع دقائق. ستلاحظ ربط أداة تصحيح الأخطاء هذه المرة.
Port forwarding pod/mynodejsapp-6bbcf847cd-vqr6v in namespace default, remote port 9229 -> http://127.0.0.1:9229 [mynodejsapp]Debugger attached.
- يتغيّر لون شريط الحالة السفلي من الأزرق إلى البرتقالي للإشارة إلى أنّه في "وضع تصحيح الأخطاء".
- في العرض
Kubernetes Run/Debug، لاحظ أنّه تم بدء تشغيل حاوية قابلة للتصحيح
**************URLs***************** Forwarded URL from service mynodejsapp-service: http://localhost:8080 Debuggable container started pod/mynodejsapp-deployment-6bc7598798-xl9kj:mynodejsapp (default) Update succeeded ***********************************
استخدام نقاط الإيقاف
- افتح
src/index.js - ابحث عن العبارة التي تقول
var message="Greetings from Node"; - أضِف نقطة توقّف إلى هذا السطر من خلال النقر على المساحة الفارغة على يمين رقم السطر. سيظهر مؤشر أحمر للإشارة إلى أنّه تم ضبط نقطة الإيقاف.
- أعِد تحميل المتصفّح ولاحظ أنّ أداة تصحيح الأخطاء توقف العملية عند نقطة التوقف وتتيح لك التحقّق من المتغيرات وحالة التطبيق الذي يتم تشغيله عن بُعد في GKE.
- انقر للأسفل في قسم المتغيّرات إلى أن تجد المتغيّر
"message". - نفِّذ السطر من خلال النقر على "التنفيذ خطوة بخطوة"

- لاحظ تغيير القيمة الحالية للمتغيّر
"message"إلى"Greetings from Node" - انقر مرّتين على اسم المتغيّر "target" (الهدف)، وفي النافذة المنبثقة، غيِّر القيمة إلى قيمة مختلفة مثل
"Hello from Node" - انقر على الزر "متابعة" في لوحة التحكّم الخاصة بتصحيح الأخطاء
- راجِع الردّ في المتصفّح الذي يعرض الآن القيمة المعدَّلة التي أدخلتها للتو.
- أوقِف وضع "تصحيح الأخطاء" من خلال الضغط على زر الإيقاف
وأزِل نقطة التوقف من خلال النقر عليها مرة أخرى.
5- تطوير خدمة REST بسيطة لإنشاء البيانات وقراءتها وتعديلها وحذفها
في هذه المرحلة، يكون تطبيقك قد تم إعداده بالكامل للتطوير ضِمن حاوية، ويكون قد تم إرشادك خلال سير عمل التطوير الأساسي باستخدام Cloud Code. في الأقسام التالية، ستتدرب على ما تعلّمته من خلال إضافة نقاط نهاية لخدمة REST تتصل بقاعدة بيانات مُدارة في Google Cloud.
ضبط التبعيات
يستخدم الرمز البرمجي للتطبيق قاعدة بيانات للاحتفاظ ببيانات خدمة REST. تأكَّد من توفّر التبعيات من خلال إضافة ما يلي في الملف package.json
- أضِف اعتماديتَين أخريَين
pgوsequelizeإلى ملفpackage.jsonلإنشاء تطبيق CRUD باستخدام Postgres. ستبدو المشاركة بعد نشر التغييرات على قسم التبعيات على النحو التالي.
"dependencies": {
"express": "^4.16.4",
"pg": "^8.7.3",
"sequelize": "^6.17.0"
}
كتابة رمز خدمة REST
- إضافة الرمز البرمجي لتطبيق CRUD إلى هذا التطبيق
wget -O app.zip https://github.com/GoogleCloudPlatform/container-developer-workshop/raw/main/labs/nodejs/app.zip
unzip app.zip
يحتوي هذا الرمز على
- مجلد models الذي يحتوي على نموذج العنصر
item - مجلد وحدات التحكّم الذي يحتوي على الرمز البرمجي الذي ينفّذ عمليات الإنشاء والقراءة والتعديل والحذف
- مجلد routes الذي يوجّه أنماط عناوين URL معيّنة إلى مكالمات مختلفة
- مجلد config يتضمّن تفاصيل الاتصال بقاعدة البيانات
- يُرجى العِلم أنّ إعدادات قاعدة البيانات في ملف
db.config.jsتشير إلى متغيّرات البيئة التي يجب توفيرها للاتصال بقاعدة البيانات. عليك أيضًا تحليل الطلب الوارد لترميز عنوان URL. - أضِف مقتطف الرمز التالي في
src/index.jsلتتمكّن من الربط برمز CRUD من ملف JavaScript الرئيسي قبل القسم الأخير الذي يبدأ بـapp.listen(PORT, () => {مباشرةً.
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true,
})
)
const db = require("../app/models");
db.sequelize.sync();
require("../app/routes/item.routes")(app);
- عدِّل عملية النشر في الملف
deployment.yamlلإضافة متغيرات البيئة لتوفير معلومات الاتصال بقاعدة البيانات.
عدِّل إدخال المواصفات في نهاية الملف ليتطابق مع التعريف التالي
spec:
containers:
- name: mynodejsapp
image: mynodejsapp
env:
- name: DB_HOST
value: ${DB_INSTANCE_IP}
- name: DB_PORT
value: "5432"
- name: DB_USER
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: username
- name: DB_PASS
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: password
- name: DB_NAME
valueFrom:
secretKeyRef:
name: gke-cloud-sql-secrets
key: database
- استبدِل قيمة DB_HOST بعنوان قاعدة البيانات.
export DB_INSTANCE_IP=$(gcloud sql instances describe mytest-instance \
--format=json | jq \
--raw-output ".ipAddresses[].ipAddress")
envsubst < deployment.yaml > deployment.new && mv deployment.new deployment.yaml
نشر التطبيق والتحقّق من صحته
- في اللوحة أسفل "محرّر Cloud Shell"، انقر على
Cloud Codeثم علىDebug on Kubernetesفي أعلى الشاشة. - عند اكتمال عملية الإنشاء والاختبارات، ستظهر الرسالة التالية في علامة التبويب "الإخراج":
Resource deployment/mynodejsapp status completed successfully، وسيتم إدراج عنوان URL: "Forwarded URL from service mynodejsapp: http://localhost:8080" - أضِف بعض العناصر.
من "وحدة Cloudshell الطرفية"، شغِّل الأوامر أدناه
URL=localhost:8080
curl -X POST $URL/items -d '{"itemName":"Body Spray", "itemPrice":3.2}' -H "Content-Type: application/json"
curl -X POST $URL/items -d '{"itemName":"Nail Cutter", "itemPrice":2.5}' -H "Content-Type: application/json"
- اختبِر طلب GET من خلال تشغيل $URL/items في المتصفّح. يمكنك أيضًا تشغيل curl من سطر الأوامر.
curl -X GET $URL/items
- اختبار الحذف: جرِّب الآن حذف عنصر من خلال تنفيذ ما يلي. غيِّر قيمة item-id إذا لزم الأمر.
curl -X DELETE $URL/items/1
This throws an error message
{"message":"Could not delete Item with id=[object Object]"}
تحديد المشكلة وحلّها
- أعِد تشغيل التطبيق في "وضع تصحيح الأخطاء" وابحث عن المشكلة. إليك بعض النصائح:
- ندرك أنّ هناك مشكلة في الأمر DELETE لأنّه لا يعرض النتيجة المطلوبة. لذلك، عليك ضبط نقطة الإيقاف في الطريقة
itemcontroller.js->exports.delete. - نفِّذ التعليمات البرمجية خطوة بخطوة وراقِب المتغيرات في كل خطوة لملاحظة قيم المتغيرات المحلية في النافذة اليمنى.
- لمراقبة قيم معيّنة، مثل
request.params، أضِف هذا المتغيّر إلى نافذة "المراقبة".
- لاحظ أنّ القيمة المعيّنة لـ
idهيundefined. غيِّر الرمز البرمجي لحلّ المشكلة.
سيبدو مقتطف الرمز الثابت على النحو التالي.
// Delete a Item with the specified id in the request
exports.delete = (req, res) => {
const id = req.params.id;
- بعد إعادة تشغيل التطبيق، اختبِر مرة أخرى من خلال محاولة الحذف.
- أوقِف جلسة تصحيح الأخطاء من خلال النقر على المربّع الأحمر في شريط أدوات تصحيح الأخطاء

6. تنظيف
تهانينا! في هذا الدرس التطبيقي، أنشأت تطبيق Nodejs جديدًا من البداية وأعددته للعمل في وضع النشر السريع باستخدام الحاويات. بعد ذلك، نشرت تطبيقك وأصلحت أخطاءه في مجموعة GKE بعيدة باتّباع مسار المطوّر نفسه المتوفّر في حِزم التطبيقات التقليدية.
لإجراء عملية تنظيف بعد إكمال الدرس التطبيقي، اتّبِع الخطوات التالية:
- حذف الملفات المستخدَمة في المختبر
cd ~ && rm -rf mynodejsapp && rm -f setup.sh
- احذف المشروع لإزالة جميع البنية الأساسية والموارد ذات الصلة