Docker وRust: حاويات التطبيقات من الألف إلى الياء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: لماذا Docker وRust هما الثنائي المثالي



تتطلب تطوير البرمجيات الحديثة ليس فقط كتابة كود فعال، بل أيضاً إنشاء بيئة موثوقة لتنفيذه. Rust هي لغة برمجة أنظمة، معروفة بأدائها العالي وأمان الذاكرة، وهي مثالية لإنشاء خدمات عالية التحميل. Docker بدوره يوفر حاويات خفيفة ومعزولة، تتيح حزم التطبيق مع جميع تبعياته.



دمج هاتين التقنيتين يمنح المطورين أداة قوية: ملف ثنائي مترجم لـ Rust، موضوع في حاوية صغيرة الحجم، يعمل بسرعة وأمان وقابلية توقع على أي منصة. في هذه المقالة، سننتقل من مثال بسيط إلى حل جاهز للإنتاج، وسنناقش الأخطاء الشائعة ونتعلم كيفية تحسين الصور.



الأساسيات: إنشاء تطبيق Rust بسيط في Docker



الخطوة 1: إعداد مشروع Rust



للبدء، سننشئ تطبيق ويب بسيطاً بلغة Rust باستخدام الإطار الشهير actix-web. هذا ليس ضرورياً، لكنه يعطي مثالاً عملياً على العمل مع الشبكة داخل الحاوية.



أنشئ مشروعاً جديداً:



cargo new rust-docker-appcd rust-docker-app


أضف التبعية في Cargo.toml:



[dependencies]actix-web = "4"


استبدل محتوى src/main.rs بـ:



use actix_web::{web, App, HttpServer, Responder};

async fn index() -> impl Responder { "Hello from Rust in Docker!"}

#[actix_web::main]async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new().route("/", web::get().to(index)) }) .bind("0.0.0.0:8080")? .run() .await}


الخطوة 2: Dockerfile بسيط



Dockerfile أساسي لتطبيق Rust يبدو كالتالي:



FROM rust:latest

WORKDIR /appCOPY . .

RUN cargo build --release

EXPOSE 8080

CMD ["./target/release/rust-docker-app"]


هذا الأسلوب يعمل، لكن له عيوب خطيرة: الصورة الناتجة كبيرة جداً (أكثر من 1 جيجابايت)، وكل إعادة بناء تقوم بتحميل جميع التبعيات من جديد.



التحسين: البناء متعدد المراحل وتقليل حجم الصورة



البناء متعدد المراحل (Multi-stage build)



التقنية الأساسية لمطوري Rust هي استخدام البناء متعدد المراحل. الفكرة بسيطة: في المرحلة الأولى، نستخدم صورة كاملة مع المترجم والأدوات، وفي المرحلة الثانية، نستخدم صورة صغيرة الحجم ننسخ فيها فقط الملف الثنائي النهائي.



# المرحلة 1: البناءFROM rust:latest AS builder

WORKDIR /appCOPY Cargo.toml Cargo.lock ./RUN mkdir src && echo "fn main() {}" > src/main.rsRUN cargo build --release 2>/dev/null || true

COPY src/ src/RUN cargo build --release

# المرحلة 2: صورة صغيرة الحجمFROM debian:bookworm-slim

WORKDIR /appCOPY --from=builder /app/target/release/rust-docker-app .

EXPOSE 8080CMD ["./rust-docker-app"]


لماذا يعمل هذا؟ أول أمر RUN cargo build يخزن التبعيات مؤقتاً. عندما تغير الكود المصدري فقط، لا يعيد Docker بناء التبعيات من جديد، مما يسرع عملية البناء بشكل كبير.



استخدام Alpine للضغط الأقصى



إذا كنت بحاجة إلى أصغر حجم للصورة، استخدم alpine كمرحلة نهائية. الملفات الثنائية لـ Rust تكون مرتبطة بشكل ثابت (statically linked)، لذلك لا حاجة لمكتبات إضافية.



# المرحلة النهائية مع AlpineFROM alpine:latest

WORKDIR /appCOPY --from=builder /app/target/release/rust-docker-app .

EXPOSE 8080CMD ["./rust-docker-app"]


حجم الصورة في هذه الحالة يمكن أن يكون 5-15 ميجابايت فقط بدلاً من 1+ جيجابايت!



تقنيات متقدمة: التخزين المؤقت والأمان



التخزين المؤقت للتبعيات باستخدام sccache



للمشاريع الكبيرة، يمكن استخدام

المدونات

توصيات الكتب