تثبيت Docker على خادم Ubuntu VPS بالطريقة الرسمية
- ٣ أكتوبر ٢٠٢٦
- ٠٩:٠٠ ص
- بقلم Adrien Roche
- دروس

قبل أن تبدأ: خادم 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 الخاص بـ Docker | docker-ce من download.docker.com | موصى بها: إصدارات حديثة، وتحديثات عبر apt upgrade، مع تضمين إضافتي Compose و Buildx. |
| مستودع universe في Ubuntu | docker.io | تعمل، لكن بنية Ubuntu متأخرة عن المصدر وتفتقر إلى الإضافات. |
| Snap | snap 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؛ ويوضّح دليلنا حول فحص المنافذ المفتوحة على لينكس كيفية قراءة تلك المخرجات والتأكد من الانكشاف من الخارج.
حلّان نظيفان، مرتّبان حسب الأفضلية:
- اربط المنافذ المنشورة بواجهة loopback. فالخيار
-p 127.0.0.1:8080:80يبقي الخدمة متاحة من الخادم نفسه فقط، عادةً خلف وكيل عكسي مثل nginx أو Caddy تعرضه عن قصد. أما الحاويات التي تتخاطب فيما بينها فقط فلا تحتاج إلى-pإطلاقًا. - رشّح في سلسلة
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، وكيف أحدّثه؟
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"؟
root:docker، لذا يحصل المستخدم العادي على permission denied. إما أن تسبق أوامرك بـ sudo أو تضيف نفسك عبر sudo usermod -aG docker $USER، ثم تبدأ جلسة دخول جديدة (أو تشغّل newgrp docker) لأن تغييرات المجموعات لا تسري إلا على الجلسات الجديدة. وإذا استمر الخطأ، فتحقق من عضويتك بـ groups، وتأكد من عمل الخدمة عبر systemctl status docker، واحرص على ألا يشير DOCKER_HOST إلى مقبس rootless غير موجود.هل أثبّت Docker عبر snap أم apt على Ubuntu Server؟
daemon.json وللبيانات، ووتيرة تحديثها يتحكم بها snapd لا أنت. وتظهر هذه القيود على شكل رسائل permission denied غامضة وإخفاقات في تركيب المجلدات. أما حزم apt فتتبع أعراف Ubuntu المعتادة، وتتكامل مع systemd بشكل طبيعي، وتتلقى التحديثات الرسمية عبر نفس أمر apt upgrade الذي تستخدمه أصلًا.كم يحتاج خادم Docker من الذاكرة ومساحة القرص؟
/var/lib/docker، و20 غيغابايت تمتلئ سريعًا دون docker system prune وتدوير السجلات. وفضّل معالجًا وذاكرة مخصصين على الحصص القابلة للاندفاع، لأن عمليات البناء ترتفع بحدة والحاويات لا تتعامل مع التبديل بسلاسة.Adrien Roche, محرر البنية التحتية والاستضافة
مهندس أنظمة بخبرة تزيد عن 10 سنوات في تشغيل أساطيل Windows Server وLinux. يدير أدريان وثائق البنية التحتية في rdp.monster ويكتب أدلتنا حول RDP واستضافة VPS وإدارة الخوادم والشبكات وأدوات الخصوصية.




