العودة إلى المدونة

إعداد البروكسي في دوكر لسحب الصور وتطبيقات الحاويات: دليل كامل

نستعرض كيفية إعداد الوكيل في دوكر لتنزيل الصور عبر جدران الحماية المؤسسية وللتطبيقات داخل الحاويات - مع أمثلة على التكوين وسيناريوهات حقيقية.

📅١٦ شوال ١٤٤٧ هـ
```html

هل تعمل مع Docker في شبكة مؤسسية، على خادم ذو وصول محدود، أو ترغب في أن تتصل حاوياتك بالإنترنت من خلال عنوان IP محدد؟ بدون إعداد بروكسي صحيح، لن يتمكن Docker من تنزيل الصور من Docker Hub أو أي سجل آخر. في هذه المقالة، سنستعرض جميع مستويات البروكسي - من الخادم إلى الحاوية المنفصلة.

لماذا يحتاج Docker إلى بروكسي

Docker هو أداة تتواصل باستمرار مع الموارد الخارجية. في كل docker pull أو docker build، يقوم الخادم بالاتصال بـ Docker Hub، أو GitHub Container Registry، أو Google Container Registry، أو سجل خاص بك. وهنا تبدأ المشاكل.

الحالات التي لا يمكن الاستغناء فيها عن البروكسي:

  • شبكة مؤسسية مع جدار ناري - يجب أن يمر كل حركة المرور عبر خادم البروكسي المؤسسي، وإلا سيتم حظر الاتصال.
  • قيود جغرافية - Docker Hub أو سجلات معينة غير متاحة من بلدك أو مركز البيانات الخاص بك.
  • خادم محدود بدون اتصال مباشر بالإنترنت - VPS في دائرة مغلقة، حيث يتوفر الإنترنت فقط عبر بوابة.
  • التحكم في حركة المرور الصادرة من الحاويات - ترغب في أن تتصل التطبيقات داخل الحاويات بالشبكة عبر عنوان IP محدد، على سبيل المثال، لجمع البيانات، أو طلبات API، أو اختبار المحتوى المعتمد على الجغرافيا.
  • إخفاء الهوية - إخفاء عنوان IP الحقيقي للخادم عند الاتصال بالخدمات الخارجية من الحاوية.
  • تحديد معدل الطلبات - يحدد Docker Hub عدد طلبات السحب للمستخدمين المجهولين (100 سحب خلال 6 ساعات). يمكن تجاوز هذا القيد عبر بروكسي مع تدوير IP.

من المهم أن نفهم أن Docker ليس تطبيقًا واحدًا، بل هو نظام يتكون من عدة مكونات. يعيش الخادم (dockerd) على المضيف ويقوم بسحب الصور. الحاويات هي عمليات معزولة بإعدادات شبكية خاصة بها. لذلك، فإن إعداد البروكسي للخادم وللحاويات هو مهمتان مختلفتان يتم حلهما بطرق مختلفة.

ثلاثة مستويات من البروكسي في Docker

قبل الغوص في التكوينات، يجب فهم الهيكلية. في Docker، هناك ثلاثة مستويات مستقلة، كل منها يتطلب إعداد بروكسي منفصل:

المستوى ماذا يفعل أين يتم الإعداد
خادم Docker يسحب الصور (docker pull)، يتصل بالسجلات تجاوز systemd أو daemon.json
بناء Docker ينفذ الأوامر أثناء بناء الصورة (RUN apt-get، pip install، إلخ) ARG وENV في Dockerfile أو --build-arg
حاوية وقت التشغيل تطبيق قيد التشغيل يقوم بإجراء طلبات HTTP ENV عند docker run أو في docker-compose.yml

خطأ شائع هو إعداد البروكسي على مستوى واحد فقط والتعجب من سبب عدم سحب الصور أو عدم رؤية التطبيق للبروكسي. دعونا نستعرض كل مستوى بالتفصيل.

إعداد بروكسي لخادم Docker (سحب الصور)

هذه هي الإعدادات الأكثر أهمية إذا كنت ترغب في سحب الصور عبر البروكسي. خادم Docker هو خدمة نظامية يتم تشغيلها عبر systemd. لا يرى متغيرات البيئة الخاصة بك أو حتى root. يجب تمرير البروكسي إلى بيئة الخدمة.

الطريقة 1: عبر تجاوز systemd (موصى بها)

أنشئ دليلًا لتجاوز إعدادات الخدمة:

sudo mkdir -p /etc/systemd/system/docker.service.d

أنشئ ملفًا /etc/systemd/system/docker.service.d/http-proxy.conf بالمحتوى التالي:

[Service]
Environment="HTTP_PROXY=http://username:password@proxy-host:port"
Environment="HTTPS_PROXY=http://username:password@proxy-host:port"
Environment="NO_PROXY=localhost,127.0.0.1,::1,your-private-registry.example.com"

إذا كان البروكسي بدون مصادقة - فقط قم بإزالة username:password@. بعد إنشاء الملف، أعد تحميل تكوين systemd وأعد تشغيل Docker:

sudo systemctl daemon-reload
sudo systemctl restart docker

تحقق من أن الإعدادات قد تم تطبيقها:

sudo systemctl show --property=Environment docker

يجب أن تظهر متغيراتك HTTP_PROXY و HTTPS_PROXY في الإخراج.

الطريقة 2: عبر ~/.docker/config.json (Docker Desktop والإصدارات الجديدة)

بدءًا من Docker Engine 23.0، تم تقديم طريقة أكثر ملاءمة - إعداد البروكسي عبر ملف تكوين العميل. أنشئ أو عدل ملف ~/.docker/config.json:

{
  "proxies": {
    "default": {
      "httpProxy": "http://username:password@proxy-host:port",
      "httpsProxy": "http://username:password@proxy-host:port",
      "noProxy": "localhost,127.0.0.1,::1"
    }
  }
}

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

💡 مهم حول NO_PROXY

دائمًا أضف إلى NO_PROXY عناوين سجلاتك الداخلية والخدمات. خلاف ذلك، سيحاول Docker الوصول إليها عبر البروكسي ويواجه أخطاء في الاتصال. قائمة نموذجية: localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

بروكسي داخل الحاوية أثناء البناء (وقت البناء)

عندما يقوم Docker ببناء صورة وينفذ أوامر مثل RUN apt-get install، RUN pip install أو RUN npm install - يتم تنفيذ هذه الأوامر داخل حاوية مؤقتة. ليس لديها وصول افتراضي إلى بروكسي المضيف. يجب تمرير البروكسي بوضوح عبر وسائط البناء.

تمرير البروكسي عبر --build-arg

docker build \
  --build-arg HTTP_PROXY=http://proxy-host:port \
  --build-arg HTTPS_PROXY=http://proxy-host:port \
  --build-arg NO_PROXY=localhost,127.0.0.1 \
  -t my-image .

الإعداد في Dockerfile

إذا كان البروكسي مطلوبًا فقط في مرحلة البناء ولا ترغب في أن يتم تضمينه في الصورة النهائية - استخدم ARG، وليس ENV:

FROM ubuntu:22.04

# إعلان عن وسائط البناء
ARG HTTP_PROXY
ARG HTTPS_PROXY
ARG NO_PROXY

# استخدامها في الأوامر
RUN apt-get update && apt-get install -y curl wget

# بعد هذه الكتلة، لن يكون البروكسي في ENV للحاوية

إذا كان البروكسي مطلوبًا أيضًا في الحاوية قيد التشغيل - استخدم ENV:

FROM python:3.11

ENV HTTP_PROXY=http://proxy-host:port
ENV HTTPS_PROXY=http://proxy-host:port
ENV NO_PROXY=localhost,127.0.0.1

RUN pip install requests beautifulsoup4

CMD ["python", "app.py"]

⚠️ انتبه: الأمان

لا تقم بتشفير اسم المستخدم وكلمة المرور للبروكسي مباشرة في Dockerfile إذا كانت الصورة ستكون عامة أو ستدخل في مستودع. استخدم --build-arg ومرر القيم من متغيرات البيئة في نظام CI/CD. يمكن أن تظهر الأمر docker history قيم ARG، لذلك استخدم أسرار Docker BuildKit للسرية.

بروكسي للحاوية قيد التشغيل (وقت التشغيل)

هذا هو السيناريو الأكثر شيوعًا للتطبيقات التي تقوم بإجراء طلبات HTTP أثناء التشغيل - مثل برامج جمع البيانات، والروبوتات، والميكروسيرفيسات التي تحتاج إلى الخروج عبر عنوان IP محدد. هنا، يكون الإعداد بسيطًا للغاية: يجب تمرير متغيرات البيئة عند تشغيل الحاوية.

عبر docker run

docker run \
  -e HTTP_PROXY=http://username:password@proxy-host:port \
  -e HTTPS_PROXY=http://username:password@proxy-host:port \
  -e NO_PROXY=localhost,127.0.0.1 \
  my-image

معظم مكتبات HTTP الشائعة تلتقط تلقائيًا متغيرات HTTP_PROXY و HTTPS_PROXY: Python requests، curl، wget، Go's net/http، Node.js https-proxy-agent وغيرها. لا تحتاج إلى كتابة أي شيء إضافي في الكود.

عبر ملف .env

من الأسهل تخزين الإعدادات في ملف .env وتمريره بالكامل:

# ملف .env
HTTP_PROXY=http://username:password@proxy-host:port
HTTPS_PROXY=http://username:password@proxy-host:port
NO_PROXY=localhost,127.0.0.1
docker run --env-file .env my-image

بروكسي SOCKS5 في الحاوية

إذا كنت تستخدم بروكسي SOCKS5 (على سبيل المثال، البروكسي السكنية تدعم عادةً هذا البروتوكول)، فإن الصيغة تختلف قليلاً:

docker run \
  -e ALL_PROXY=socks5://username:password@proxy-host:port \
  my-image

لاحظ: ليست جميع المكتبات تدعم SOCKS5 عبر متغير البيئة بدون تبعيات إضافية. تتطلب مكتبة Python requests تثبيت requests[socks]، ويجب أن يتم بناء curl مع دعم libcurl-socks.

بروكسي في Docker Compose

في المشاريع الحقيقية، نادرًا ما يتم استخدام docker run بمفرده. غالبًا ما يتم العمل مع Docker Compose، حيث يتم وصف عدة خدمات في ملف واحد. يتم إعداد البروكسي هنا على مستوى كل خدمة أو عبر ملف المتغيرات.

الخيار 1: البيئة في docker-compose.yml

version: '3.8'

services:
  scraper:
    image: my-scraper:latest
    environment:
      - HTTP_PROXY=http://username:password@proxy-host:port
      - HTTPS_PROXY=http://username:password@proxy-host:port
      - NO_PROXY=localhost,127.0.0.1
    restart: unless-stopped

  api:
    image: my-api:latest
    # هذه الخدمة بدون بروكسي - تتصل فقط بالموارد الداخلية
    ports:
      - "8080:8080"

الخيار 2: عبر ملف .env (موصى به)

أنشئ .env في الدليل الذي يحتوي على docker-compose.yml. يقوم Docker Compose بالتقاط هذا الملف تلقائيًا:

# .env
PROXY_HOST=proxy-host
PROXY_PORT=8080
PROXY_USER=username
PROXY_PASS=password
version: '3.8'

services:
  scraper:
    image: my-scraper:latest
    environment:
      - HTTP_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
      - HTTPS_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
      - NO_PROXY=localhost,127.0.0.1

بروكسي أثناء البناء في Compose

إذا كان في Compose قسم build وتحتاج إلى تمرير البروكسي أثناء مرحلة البناء:

version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      args:
        HTTP_PROXY: http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
        HTTPS_PROXY: http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
    environment:
      - HTTP_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
      - HTTPS_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}

ما هو نوع البروكسي الذي يجب اختياره لـ Docker

يعتمد اختيار نوع البروكسي على المهمة. بالنسبة لبيئات Docker، هناك ثلاثة أنواع رئيسية، لكل منها مكانتها الخاصة:

نوع البروكسي السرعة الخصوصية أفضل سيناريو لـ Docker
مركز البيانات ⚡ عالية متوسطة سحب الصور، خطوط CI/CD، تجاوز تحديد معدل Docker Hub
السكنية 🔄 متوسطة عالية جمع البيانات من المواقع المحمية، API مع قيود جغرافية، اختبار
المحمول 🔄 متوسطة قصوى تطبيقات تعمل مع API المحمول (Instagram، TikTok)

لسحب الصور وCI/CD، فإن بروكسيات مراكز البيانات هي الأمثل - فهي توفر أقصى سرعة عند تنزيل صور كبيرة (عدة جيجابايت) واتصال مستقر لبناءات طويلة.

للحاويات التي تجمع البيانات، التي تحتاج إلى تجاوز حماية المواقع والظهور كمستخدم عادي، فإن البروكسيات السكنية هي الأنسب. لديهم IP لمستخدمين حقيقيين في المنازل، مما يقلل من احتمال الحظر حتى مع الطلبات المكثفة.

للتطبيقات التي تعمل مع المنصات المحمولة - Instagram Graph API، TikTok API، والإصدارات المحمولة من الخدمات - يجب النظر في البروكسيات المحمولة. تستخدم IP لمشغلي الشبكات الخلوية وتثير الحد الأدنى من الشكوك من أنظمة مكافحة الروبوتات.

البروتوكولات: HTTP مقابل SOCKS5

يدعم خادم Docker فقط بروكسي HTTP/HTTPS - لا يعمل SOCKS5 لسحب الصور. إذا كان لديك بروكسي SOCKS5 وتحتاج إلى تنزيل الصور، سيتعين عليك استخدام محول محلي مثل privoxy أو microsocks، الذي سيقبل HTTP ويقوم بتمريره عبر SOCKS5.

بالنسبة للحاويات في وقت التشغيل، فإن الوضع أفضل: تدعم معظم مكتبات HTTP SOCKS5 مباشرة عبر متغير ALL_PROXY=socks5://....

الأخطاء الشائعة وكيفية إصلاحها

دعونا نستعرض أكثر المشاكل شيوعًا التي تواجه عند إعداد البروكسي في Docker:

الخطأ 1: تم إعداد البروكسي على المضيف، لكن Docker لا يراه

الأعراض:

خطأ في الاستجابة من الخادم: الحصول على "https://registry-1.docker.io/v2/": الاتصال مرفوض

السبب: يتم تشغيل خادم Docker كخدمة نظامية ولا يرث متغيرات البيئة الخاصة بالمستخدم الحالي، حتى لو قمت بتعيين export HTTPS_PROXY=... في الطرفية.

الحل: قم بإعداد البروكسي عبر تجاوز systemd (الطريقة 1 من القسم أعلاه). تأكد من تنفيذ systemctl daemon-reload && systemctl restart docker.

الخطأ 2: apt-get / pip / npm لا تعمل أثناء البناء

الأعراض:

خطأ:1 http://archive.ubuntu.com/ubuntu focal InRelease
تعذر الاتصال بـ archive.ubuntu.com:80

السبب: إعداد البروكسي للخادم لا ينتشر تلقائيًا إلى الأوامر داخل RUN في Dockerfile. هذه سياقات مختلفة.

الحل: قم بتمرير البروكسي عبر --build-arg أو استخدم ~/.docker/config.json مع قسم proxies (Docker 23.0+، يمرر الوسائط تلقائيًا أثناء البناء).

الخطأ 3: الخدمات الداخلية غير متاحة عبر البروكسي

الأعراض:

curl: (7) فشل الاتصال بالخدمة الداخلية.local المنفذ 8080: الاتصال مرفوض

السبب: يحاول البروكسي تمرير الطلبات إلى العناوين الداخلية التي لا يمكن الوصول إليها من الخارج.

الحل: أضف جميع النطاقات الداخلية والشبكات الفرعية إلى NO_PROXY. لقوائم الشبكات المؤسسية، القائمة النموذجية هي: localhost,127.0.0.1,::1,.internal,.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

الخطأ 4: مصادقة البروكسي لا تعمل - رموز خاصة في كلمة المرور

إذا كانت كلمة المرور تحتوي على رموز خاصة (@، #، %)، يتم تحليل URL بشكل غير صحيح.

الحل: قم بتشفير كلمة المرور في ترميز URL. على سبيل المثال، p@ss#wordp%40ss%23word. في Python، يمكنك بسرعة الحصول على النسخة المشفرة:

python3 -c "from urllib.parse import quote; print(quote('p@ss#word', safe=''))"
# الإخراج: p%40ss%23word

الخطأ 5: يعمل البروكسي، لكن شهادة SSL لا يتم التحقق منها

غالبًا ما تقوم البروكسيات المؤسسية بتنفيذ فحص SSL (MITM) واستبدال الشهادات. في هذه الحالة، يظهر Docker خطأ:

x509: شهادة موقعة من قبل سلطة غير معروفة

الحل: أضف شهادة الجذر المؤسسية إلى الموثوق بها على المضيف وأعد تشغيل Docker. على Ubuntu/Debian:

sudo cp corporate-ca.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
sudo systemctl restart docker

الخطأ 6: Kubernetes / Docker Swarm - البروكسي لا يعمل على جميع العقد

في البيئات العنقودية، يجب إعداد البروكسي على كل عقدة بشكل منفصل. بالنسبة لـ Kubernetes، يجب أيضًا إعداد متغيرات البيئة في بيانات تعريف الحاويات أو عبر ConfigMap. يمكن أتمتة ذلك عبر Ansible أو أدوات إدارة التكوين الأخرى.

الخاتمة

إعداد البروكسي في Docker ليس إعدادًا واحدًا، بل ثلاثة مستويات مستقلة: الخادم لسحب الصور، وقت البناء للبناء، ووقت التشغيل للحاويات النشطة. من خلال فهم هذه الهيكلية، يمكنك إدارة حركة المرور بشكل مرن، سواء كانت تمر عبر البروكسي أو مباشرة.

قائمة مراجعة مختصرة للإعداد الصحيح:

  • ✅ لسحب الصور - قم بإعداد تجاوز systemd مع متغيرات HTTP_PROXY و HTTPS_PROXY
  • ✅ للبناء - قم بتمرير البروكسي عبر --build-arg أو ~/.docker/config.json
  • ✅ لوقت التشغيل - استخدم متغيرات البيئة عبر -e أو --env-file
  • ✅ دائمًا قم بإعداد NO_PROXY للعناوين الداخلية
  • ✅ لا تخزن كلمات مرور البروكسي في Dockerfile - استخدم build-args وملفات .env
  • ✅ لخطوط CI/CD، اختر بروكسيات مراكز البيانات السريعة
  • ✅ للحاويات التي تجمع البيانات - استخدم البروكسيات السكنية أو المحمولة

إذا كانت تطبيقات الحاويات الخاصة بك تقوم بإجراء طلبات إلى خدمات خارجية، أو تجمع بيانات، أو تعمل مع APIs التي لديها قيود جغرافية، نوصي باستخدام البروكسيات السكنية - فهي توفر مستوى عالٍ من الثقة من قبل الخدمات وأقل خطر للحظر حتى مع العمل المكثف.

```