RDP Monster

تثبيت Docker على خادم Ubuntu VPS بالطريقة الرسمية

تثبيت Docker على خادم Ubuntu VPS بالطريقة الرسمية

قبل أن تبدأ: خادم KVM، ونسخة Ubuntu مدعومة، ومستخدم بصلاحيات sudo

لا يأتي Docker Engine بنواة خاصة به. فكل حاوية تتشارك نواة المضيف وتعتمد على namespaces و cgroups و netfilter في لينكس، ولذلك تحتاج الخدمة إلى خادم VPS تملك أنت نواته. وهذا بالضبط ما يوفّره خادم KVM (المحاكاة الكاملة). أما في الخطط القائمة على الحاويات مثل OpenVZ أو LXC، فالنواة ملك للمزوّد، وعندها إما يرفض Docker الإقلاع أو يعمل فقط إذا فعّل المضيف التداخل. تحقّق من ذلك قبل تثبيت أي شيء:

systemd-detect-virt                          # expect: kvm
. /etc/os-release && echo "$VERSION_CODENAME"   # noble (24.04) or jammy (22.04)
uname -m                                     # x86_64 or aarch64

يوفّر Docker حزمًا لنسخ Ubuntu 24.04 LTS (noble) و22.04 LTS (jammy) بمعمارية 64 بت، على x86_64 و arm64. كما تحتاج إلى مستخدم يملك صلاحيات sudo؛ إذ يفترض قسما مجموعة docker والوضع rootless أدناه حسابًا عاديًا لا حساب الجذر.

تثبيت Docker Engine من مستودع apt الرسمي

هناك أربع طرق شائعة لتثبيت Docker على Ubuntu، وواحدة فقط هي التي يوثّقها Docker ويدعمها على الخوادم:

الطريقةالحزمةالحكم
مستودع apt الخاص بـ Dockerdocker-ce من download.docker.comموصى بها: إصدارات حديثة، وتحديثات عبر apt upgrade، مع تضمين إضافتي Compose و Buildx.
مستودع universe في Ubuntudocker.ioتعمل، لكن بنية Ubuntu متأخرة عن المصدر وتفتقر إلى الإضافات.
Snapsnap install dockerتثبيت محصور بمسارات خاصة به؛ مصدر متكرر لمفاجآت "permission denied". تجنّبه على الخوادم.
سكربت التثبيت السريعget.docker.comالحزم نفسها، لكنها تُمرَّر دون مراجعة إلى صدفة الجذر. للأجهزة المؤقتة فقط.

الخطوة 1: إزالة الحزم المتعارضة

إذا كانت صورة الخادم تحتوي مسبقًا على docker.io من Ubuntu، أو نسخة قديمة من docker-compose، أو podman-docker، فأزلها حتى لا تتنازع البنيتان على /usr/bin/docker. هذه الحلقة مأخوذة من وثائق Docker وغير مؤذية على نظام نظيف، ولا تمسّ /var/lib/docker:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
  sudo apt-get remove $pkg
done

الخطوة 2: إضافة مفتاح GPG ومصدر apt الخاصين بـ Docker

يوضع المفتاح في /etc/apt/keyrings/ ويُشار إليه بـ signed-by=، ما يحصر نطاقه في هذا المستودع وحده بدل الوثوق به عالميًا عبر apt-key المهجور. ويُقرأ الاسم الرمزي للنسخة من /etc/os-release، لذا تعمل الكتلة نفسها على 24.04 و22.04:

sudo apt-get update
sudo apt-get install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

خطأ التوقيع عند تنفيذ apt-get update الأخير يعني في الغالب أن ملف المفتاح غير قابل للقراءة؛ أعد تنفيذ سطر chmod.

الخطوة 3: تثبيت المحرّك وإضافاته

sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

الحزمة docker-ce هي الخدمة، وdocker-ce-cli هي العميل، وcontainerd.io هو زمن التشغيل الأساسي، بينما توفّر الإضافتان الأمرين docker buildx وdocker compose. وعلى Ubuntu يشغّل سكربت ما بعد التثبيت الخدمة docker.service فورًا ويفعّلها عند الإقلاع.

الخطوة 4: التحقق عبر hello-world

sudo docker run hello-world
docker --version
sudo docker info | head -n 20

الاختبار hello-world حاسم: العميل يتواصل مع الخدمة، والخدمة تسحب صورة صغيرة من Docker Hub، وتنشئ حاوية، وتشغّلها وتعيد مخرجاتها. فإذا ظهرت لك عبارة "Hello from Docker!" فكل الطبقات تعمل. وعلى تثبيت سليم لـ 24.04 أو 22.04، يعرض docker info القيمتين Storage Driver: overlay2 وCgroup Version: 2.

تشغيل Docker دون sudo: مجموعة docker

تستمع الخدمة على مقبس يونكس /var/run/docker.sock المملوك لـ root:docker، لذا يستطيع أعضاء مجموعة docker استخدام سطر الأوامر دون sudo:

sudo groupadd docker          # usually exists already; harmless if it does
sudo usermod -aG docker $USER
newgrp docker                 # or log out and back in
docker run hello-world

انتبه إلى ما منحته للتو. فكل من يصل إلى هذا المقبس يمكنه تنفيذ docker run -v /:/host --privileged ... وقراءة أي ملف على الخادم أو تعديله، ما يجعل الانتماء إلى مجموعة docker معادلًا لصلاحيات الجذر، دون طلب كلمة مرور ودون أثر في سجل sudo. تعامل معه تمامًا كصلاحية sudo؛ ويشرح دليلنا حول تبديل المستخدمين وتصعيد الصلاحيات على Ubuntu أهمية هذا التمييز على جهاز متعدد المستخدمين.

إضافة Docker Compose

توفّر حزمة docker-compose-plugin الإصدار الثاني من Compose عبر الأمر الفرعي docker compose (بمسافة). أما ملف docker-compose القديم المكتوب بلغة Python فقد انتهى دعمه ولا ينبغي تثبيته إلى جانبه. تحقّق من الإصدار، ثم اختبره بملف compose.yaml بسيط:

docker compose version

mkdir -p ~/web && cd ~/web
cat > compose.yaml <<'EOF'
services:
  web:
    image: nginx:alpine
    ports:
      - "127.0.0.1:8080:80"
    restart: unless-stopped
EOF

docker compose up -d
docker compose ps
curl -I http://127.0.0.1:8080
docker compose down

هناك تفصيلان مقصودان: restart: unless-stopped يعيد تشغيل الحاوية بعد إعادة الإقلاع، والمنفذ مربوط بـ 127.0.0.1 لا بكل الواجهات، لأسباب يوضّحها قسم الجدار الناري.

الوضع rootless: خدمة لا تعمل بصلاحيات الجذر

يشغّل الوضع rootless الخدمة والحاويات داخل فضاء أسماء المستخدم، بحيث ينتهي أي هروب من الحاوية إلى حساب بلا صلاحيات بدل حساب الجذر. وهو الخيار الصحيح حين يتشارك عدة أشخاص خادمًا واحدًا. أما المتطلبات فهي نطاقات UID/GID الفرعية (ينشئها Ubuntu للمستخدمين العاديين في /etc/subuid و/etc/subgid)، وأدوات uidmap، وجلسة D-Bus للمستخدم، وحزمة الإضافات rootless من Docker:

sudo apt-get install -y uidmap dbus-user-session docker-ce-rootless-extras
grep "^$USER:" /etc/subuid /etc/subgid   # each should show a range of 65536 IDs

# optional: stop the system-wide daemon if you only want rootless
sudo systemctl disable --now docker.service docker.socket

dockerd-rootless-setuptool.sh install

تنشئ أداة الإعداد وحدة systemd خاصة بكل مستخدم وتطبع المتغيّرين اللذين تحتاجهما الصدفة. أضفهما إلى ~/.bashrc، ثم اجعل خدمة المستخدم تبدأ عند الإقلاع دون تسجيل دخول:

export PATH=/usr/bin:$PATH
export DOCKER_HOST=unix:///run/user/$(id -u)/docker.sock

systemctl --user enable docker
sudo loginctl enable-linger $(whoami)

للوضع rootless حدود حقيقية: لا يمكن نشر المنافذ دون 1024 إلا إذا نفّذت sudo setcap cap_net_bind_service=ep $(which rootlesskit) وأعدت تشغيل خدمة المستخدم، كما أن شبكات overlay غير متاحة، والبيانات تُخزَّن في ~/.local/share/docker. وعلى Ubuntu 24.04 يقيّد AppArmor فضاءات أسماء المستخدم غير المميزة؛ وتتضمن حزم deb الملف التعريفي الذي يحتاجه rootlesskit، لكن التثبيت عبر ملف ثنائي ساكن يتطلب إضافته يدويًا كما هو موضّح في وثائق rootless.

سلوك الإقلاع والتخزين وتدوير السجلات

أمران منفصلان يحدّدان ما إذا كانت حاوياتك ستعمل بعد إعادة الإقلاع: يجب تفعيل الخدمة، ويجب أن تحمل كل حاوية سياسة إعادة تشغيل. تفعّل حزم Ubuntu الخدمة نيابة عنك؛ تأكّد من ذلك، وإذا بدت حالات الوحدات غامضة فإن مرجعنا حول سرد الخدمات باستخدام systemctl يشرح كل عمود:

systemctl is-enabled docker.service containerd.service
sudo systemctl enable docker.service containerd.service   # only if the line above said disabled

الحاويات التي تُشغَّل دون --restart تبقى متوقفة بعد إعادة الإقلاع؛ استخدم --restart unless-stopped في سطر الأوامر أو restart: unless-stopped في Compose لأي خدمة دائمة.

كل ما يخزّنه Docker (طبقات الصور، وأنظمة ملفات الحاويات، والأحجام، والسجلات) يقع تحت /var/lib/docker، وهو المجلد الذي يملأ القرص على خادم صغير. راقبه بـ docker system df، واسترجع المساحة من الطبقات المعلّقة بـ docker system prune، واقرأ الرسالة قبل إضافة -a التي تحذف أيضًا كل صورة لا تستخدمها حاوية قيد التشغيل. وإذا كان الخادم يملك قرصًا ثانيًا، فوجّه data-root إليه في /etc/docker/daemon.json قبل سحب أي شيء كبير.

تستحق السجلات تحذيرًا خاصًا. فالمشغّل الافتراضي json-file يكتب كل سطر من مخرجات الحاوية إلى /var/lib/docker/containers/<id>/<id>-json.log ولا ينفّذ أي تدوير ما لم تضبطه بنفسك. وحاوية كثيرة الإخراج قد تلتهم القرص كله في أسبوع. اضبط حدودًا على مستوى الخدمة منذ اليوم الأول:

sudo tee /etc/docker/daemon.json > /dev/null <<'EOF'
{
  "log-driver": "json-file",
  "log-opts": { "max-size": "10m", "max-file": "3" },
  "live-restore": true
}
EOF
sudo systemctl restart docker

تنطبق خيارات السجلات على الحاويات المنشأة بعد إعادة التشغيل، لذا أعد إنشاء الحاويات طويلة الأمد مرة واحدة. ويتيح live-restore إعادة تشغيل الخدمة للترقية دون إيقاف الحاويات العاملة.

Docker وufw: المنافذ المنشورة تتجاوز جدارك الناري

هذا هو الجزء الذي يوقع معظم الناس على خادم عام. فـ Docker يدير قواعد iptables الخاصة به: عند نشر منفذ بـ -p 8080:80 تُدرج الخدمة قاعدة DNAT في سلسلة PREROUTING ضمن جدول nat، وقاعدة قبول في FORWARD. أما قواعد ufw فتقع في INPUT التي لا تمر بها حركة التمرير أبدًا. لذلك لا أثر للأمر ufw deny 8080، وتبقى حاوية قاعدة بيانات منشورة على 0.0.0.0:5432 متاحة للإنترنت بأكمله بينما يفيد ufw بأن المنفذ محجوب. ابحث عن 0.0.0.0: في عمود PORTS ضمن docker ps، أو شغّل ss -tlnp؛ ويوضّح دليلنا حول فحص المنافذ المفتوحة على لينكس كيفية قراءة تلك المخرجات والتأكد من الانكشاف من الخارج.

حلّان نظيفان، مرتّبان حسب الأفضلية:

  1. اربط المنافذ المنشورة بواجهة loopback. فالخيار -p 127.0.0.1:8080:80 يبقي الخدمة متاحة من الخادم نفسه فقط، عادةً خلف وكيل عكسي مثل nginx أو Caddy تعرضه عن قصد. أما الحاويات التي تتخاطب فيما بينها فقط فلا تحتاج إلى -p إطلاقًا.
  2. رشّح في سلسلة DOCKER-USER. يقيّم Docker هذه السلسلة قبل قواعد FORWARD الخاصة به ولا يعيد كتابتها أبدًا. وبما أن DNAT يكون قد جرى قبل وصول الحزمة إليها، طابق المنفذ الأصلي عبر conntrack:
sudo iptables -I DOCKER-USER -i eth0 ! -s 203.0.113.10 -p tcp \
  -m conntrack --ctorigdstport 8080 --ctdir ORIGINAL -j DROP

استبدل eth0 بواجهتك العامة و203.0.113.10 بالعنوان المسموح له بالدخول. هذه القواعد غير دائمة؛ احفظها عبر حزمة iptables-persistent. أما ضبط "iptables": false في daemon.json فيعطّل شبكات الحاويات بطرق يصعب تشخيصها؛ فاتركه على حاله.

إزالة Docker بالكامل

احذف الحزم أولًا بالكامل، ثم امسح مجلدات البيانات التي يتركها apt عمدًا:

sudo apt-get purge -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo rm -rf /var/lib/docker /var/lib/containerd
sudo rm -f /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.asc
sudo apt-get autoremove -y

أما في إعداد rootless، فشغّل dockerd-rootless-setuptool.sh uninstall بحساب المستخدم أولًا ثم احذف ~/.local/share/docker بعد ذلك.

كل ما سبق يفترض خادمًا تملك فيه صلاحيات الجذر، وتتحكم في النواة، وتستطيع تعديل iptables دون إذن من أحد. وإن كنت لا تزال تبحث عن هذا الجهاز، فإن خادم VPS لينكس بتقنية KVM مع صلاحيات جذر كاملة من rdp.monster يأتي بنسخة Ubuntu 24.04 أو 22.04، مع معالج وذاكرة مخصصين، ونطاق ترددي غير محدود (ضمن الاستخدام العادل)، دون KYC، مع قبول العملات المشفّرة، ابتداءً من 8.99$ شهريًا، ويُسلَّم بعد نحو 10 ثوانٍ من تأكيد الدفع، لتتمكن من تشغيل اختبار hello-world أعلاه على خادمك الخاص فور إتمام الطلب.

الأسئلة الشائعة

أي إصدار من Docker يثبّته apt على Ubuntu، وكيف أحدّثه؟

يثبّت المستودع أحدث إصدار مستقر من Docker Engine، ويبقيه apt upgrade محدّثًا.
بعد ضبط مستودع apt الخاص بـ Docker، يسحب الأمر apt-get install docker-ce أحدث إصدار مستقر متاح للاسم الرمزي لنسخة Ubuntu لديك، وكل تنفيذ لاحق لـ sudo apt-get update && sudo apt-get upgrade يبقيك على أحدث نسخة. شغّل docker version لمعرفة إصداري العميل والخادم. ولتثبيت إصدار محدد، اعرض المرشحين بـ apt-cache madison docker-ce وثبّت docker-ce=<version> مع النسخة المطابقة من docker-ce-cli، ثم نفّذ apt-mark hold على الحزمتين.

لماذا تظهر لي رسالة "permission denied while trying to connect to the Docker daemon socket"؟

مستخدمك لا يستطيع قراءة /var/run/docker.sock؛ انضم إلى مجموعة docker أو استخدم sudo.
مقبس الخدمة مملوك لـ root:docker، لذا يحصل المستخدم العادي على permission denied. إما أن تسبق أوامرك بـ sudo أو تضيف نفسك عبر sudo usermod -aG docker $USER، ثم تبدأ جلسة دخول جديدة (أو تشغّل newgrp docker) لأن تغييرات المجموعات لا تسري إلا على الجلسات الجديدة. وإذا استمر الخطأ، فتحقق من عضويتك بـ groups، وتأكد من عمل الخدمة عبر systemctl status docker، واحرص على ألا يشير DOCKER_HOST إلى مقبس rootless غير موجود.

هل أثبّت Docker عبر snap أم apt على Ubuntu Server؟

استخدم apt مع مستودع Docker؛ فحزمة snap تضيف قيود عزل دون أي فائدة على الخادم.
فضّل apt من مستودع Docker الرسمي. فحزمة snap معزولة بصرامة: لا تستطيع قراءة ملفات خارج مجلد المنزل دون وصلات واجهات إضافية، وتستخدم مسارات مختلفة لـ daemon.json وللبيانات، ووتيرة تحديثها يتحكم بها snapd لا أنت. وتظهر هذه القيود على شكل رسائل permission denied غامضة وإخفاقات في تركيب المجلدات. أما حزم apt فتتبع أعراف Ubuntu المعتادة، وتتكامل مع systemd بشكل طبيعي، وتتلقى التحديثات الرسمية عبر نفس أمر apt upgrade الذي تستخدمه أصلًا.

كم يحتاج خادم Docker من الذاكرة ومساحة القرص؟

المحرّك نفسه خفيف؛ اختر حجم الخادم بحسب الحاويات وصورها.
يستهلك Docker Engine في وضع الخمول بضع عشرات الميغابايتات من الذاكرة، فالميزانية الحقيقية هي حِمل عملك. تطبيق ويب صغير مع قاعدة بيانات يعمل بأريحية في 2 غيغابايت؛ أما الحزم الأثقل أو عدة مشاريع فتحتاج إلى 4 غيغابايت أو أكثر. والقرص أهم مما يتوقع الكثيرون: الصور وذاكرة البناء المؤقتة والسجلات تستقر كلها في /var/lib/docker، و20 غيغابايت تمتلئ سريعًا دون docker system prune وتدوير السجلات. وفضّل معالجًا وذاكرة مخصصين على الحصص القابلة للاندفاع، لأن عمليات البناء ترتفع بحدة والحاويات لا تتعامل مع التبديل بسلاسة.

Adrien Roche, محرر البنية التحتية والاستضافة

مهندس أنظمة بخبرة تزيد عن 10 سنوات في تشغيل أساطيل Windows Server وLinux. يدير أدريان وثائق البنية التحتية في rdp.monster ويكتب أدلتنا حول RDP واستضافة VPS وإدارة الخوادم والشبكات وأدوات الخصوصية.

سجّل في برنامج الموزعين لدينا

معلوماتك

إذا كان لديك أي سؤال، contact us by clicking here !
الاسم(مطلوب)
أدخل عنوان بريدك الإلكتروني، ويجب أن يكون لديك حساب على manager.rdp.monster !

شركتك

أدخل عنوان موقعك الإلكتروني إن كان لديك موقع
اشرح بإيجاز كيف ستبيع الخدمات لعملائك. على سبيل المثال، عبر التحدث مع الأشخاص في المنتديات.

نحن نستخدم ملفات تعريف الارتباط !

نحن نستخدم ملفات تعريف الارتباط لتحسين تجربة التصفح الخاصة بك، وتقديم إعلانات أو محتوى مخصص، وتحليل حركة المرور لدينا. بالنقر على «قبول»، فإنك توافق على استخدامنا لملفات تعريف الارتباط.