تخطَّ إلى المحتوى

١٠ يوليو ٢٠٢٦ · آخر تحديث: ١٩ أكتوبر ٢٠٢٦

حل خطأ port is already allocated في Docker بالعربي

شارك المقال:

تشغّل حاويتك:

docker run -p 3000:3000 my-app

فيرفض Docker برسالة طويلة. أهم جزء فيها هو آخرها، لأن Docker يكتب رسالتين مختلفتين حسب من يحجز المنفذ:

آخر الرسالةمن يحجز المنفذ 3000أين تبحث
Bind for 0.0.0.0:3000 failed: port is already allocatedحاوية Docker أخرى تعمل الآنdocker ps
failed to bind host port 0.0.0.0:3000/tcp: address already in useبرنامج على جهازك خارج Dockerlsof أو netstat

الرسالتان كما ظهرتا حرفيًا على Docker Engine 29:

docker: Error response from daemon: failed to set up container networking:
driver failed programming external connectivity on endpoint adoring_mclaren (...):
Bind for 0.0.0.0:3000 failed: port is already allocated
docker: Error response from daemon: failed to set up container networking:
driver failed programming external connectivity on endpoint objective_tharp (...):
failed to bind host port 0.0.0.0:3000/tcp: address already in use

اسم الـ endpoint (adoring_mclaren) هو الاسم العشوائي لحاويتك الجديدة التي فشلت، وليس اسم الحاجز. لا تبحث عنه.

افهم الربط أولًا: host:container

-p 3000:3000
   ────┬ ───┬
       │    └─ منفذ الحاوية: ما يستمع عليه تطبيقك بالداخل
       └────── منفذ المضيف: ما يُفتح على جهازك، وهذا هو المتنازَع عليه

لكل حاوية شبكتها المعزولة، فعشر حاويات تستطيع كلها الاستماع على 3000 بالداخل دون أي تعارض. التعارض دائمًا على الرقم الأيسر، لأن جهازك فيه منفذ 3000 واحد فقط.

الحالة 1: port is already allocated — حاوية أخرى

اسأل Docker مباشرة من ينشر هذا المنفذ:

docker ps --filter publish=3000 --format "table {{.Names}}\t{{.Ports}}"
NAMES     PORTS
old-app   0.0.0.0:3000->3000/tcp

ثم أوقفها، أو أوقفها واحذفها:

docker stop old-app
docker rm old-app     # اختياري: الإيقاف وحده يكفي لتحرير المنفذ

الشكل الأكثر شيوعًا: مشروعا compose على نفس المنفذ

عندك مشروعان، وكلاهما فيه مثلًا قاعدة بيانات على 5432:5432. نسيت الأول يعمل وشغّلت الثاني، فيفشل الثاني بنفس الرسالة. اعرف أي مشروع يعمل:

docker compose ls
NAME   STATUS       CONFIG FILES
shop   running(1)   /home/me/shop/compose.yaml

ثم من مجلد ذلك المشروع:

docker compose down   # يوقف ويحذف حاويات المشروع وشبكته

docker compose stop يكفي أيضًا لتحرير المنفذ؛ الفرق أن down يحذف الحاويات والشبكة بدل إبقائها متوقفة.

تصحيح لمعلومة منتشرة: الحاوية المتوقفة لا تحجز المنفذ

قد تقرأ أن حاوية متوقفة "تبقى حاجزة للمنفذ حتى تُحذف". جرّبناها: بعد docker stop old-app صارت حالتها Exited بعمود PORTS فارغ، واشتغلت حاوية جديدة على 3000 فورًا. إن رأيت الخطأ بعد إيقاف حاويتك، فالأرجح:

  • حاوية أخرى تعمل (docker ps --filter publish=3000 يكشفها)، أو
  • حاويتك القديمة عادت للعمل وحدها لأنها أُنشئت بـ --restart always أو unless-stopped ثم أُعيد تشغيل Docker أو الجهاز. أوقف هذا السلوك بـ:
docker update --restart=no old-app

الحالة 2: address already in use — برنامج خارج Docker

docker ps لن يجد شيئًا هنا، لأن الحاجز ليس حاوية. ابحث في الجهاز نفسه:

# لينكس / ماك
sudo lsof -i :3000
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
python3 4939 me     3u  IPv4  11864      0t0  TCP *:3000 (LISTEN)

على لينكس يعطيك sudo ss -ltnp 'sport = :3000' نفس المعلومة إن لم يكن lsof مثبّتًا. وعلى ويندوز (PowerShell):

netstat -ano | findstr :3000     # الـ PID في آخر عمود
tasklist | findstr <PID>         # اسم البرنامج

غالبًا يكون خادم تطوير (npm run dev) نسيته في طرفية أخرى، أو قاعدة بيانات مثبّتة على الجهاز مباشرة (PostgreSQL على 5432 أو MySQL على 3306) وتحاول تشغيل نسخة Docker منها على نفس المنفذ. تفاصيل إيقاف البرنامج الحاجز على كل نظام في حل خطأ EADDRINUSE: المنفذ مستخدم.

ويندوز: منفذ "محجوز" ولا أحد يستخدمه

على Docker Desktop بويندوز قد تظهر رسالة تبدأ بـ Ports are not available وتنتهي بـ:

An attempt was made to access a socket in a way forbidden by its access permissions.

مع أن netstat لا يُظهر أي برنامج على المنفذ. السبب أن ويندوز نفسه يحجز نطاقات منافذ (تستخدمها خدمات مثل Hyper-V وWSL 2). اعرضها:

netsh interface ipv4 show excludedportrange protocol=tcp

إن كان منفذك داخل أحد النطاقات، اختر منفذ مضيف خارجها.

الحل الفوري: غيّر الرقم الأيسر

لا يهمك من الحاجز وتريد أن تكمل؟ غيّر منفذ المضيف فقط:

docker run -p 3001:3000 my-app
# التطبيق بالداخل ما زال على 3000، وأنت تفتحه على localhost:3001

وفي compose.yaml:

services:
  web:
    image: my-app
    ports:
      - "3001:3000"   # المضيف:الحاوية

وما دمت تعدّل الربط، فكّر في 127.0.0.1:

docker run -p 127.0.0.1:5432:5432 postgres

-p 5432:5432 وحدها تعني 0.0.0.0، أي أن المنفذ مفتوح على كل واجهات الشبكة في جهازك وليس فقط عليك. لقاعدة بيانات تطوير لا يحتاجها أحد غيرك، الربط على 127.0.0.1 أأمن.

بعد الحل: "اسم الحاوية مستخدم"

إذا كنت تشغّل بـ --name، ستلاحظ أن إعادة نفس الأمر بعد تحرير المنفذ تفشل هكذا:

docker: Error response from daemon: Conflict. The container name "/web" is already in use by container "5fe0499c...".
You have to remove (or rename) that container to be able to reuse that name.

السبب أن docker run الفاشل أنشأ الحاوية قبل أن يفشل في ربط المنفذ، فبقيت بحالة Created:

docker ps -a --filter name=web --format "table {{.Names}}\t{{.Status}}"
# NAMES   STATUS
# web     Created

docker rm web    # ثم أعد docker run

أو شغّل التجارب بـ --rm من البداية، فتُحذف الحاوية تلقائيًا عند إيقافها.

قائمة تحقّق

  1. اقرأ آخر الرسالة: port is already allocated يعني حاوية، وaddress already in use يعني برنامجًا على الجهاز.
  2. حاوية؟ docker ps --filter publish=3000، ثم docker stop.
  3. مشروع compose آخر؟ docker compose ls، ثم docker compose down من مجلده.
  4. برنامج على الجهاز؟ lsof -i :3000 أو netstat -ano | findstr :3000.
  5. ويندوز ولا أحد على المنفذ؟ netsh interface ipv4 show excludedportrange protocol=tcp.
  6. مستعجل؟ غيّر الرقم الأيسر: -p 3001:3000.
  7. "الاسم مستخدم" بعد الحل؟ docker rm <الاسم>.

لفهم الشبكات والمنافذ في Docker من الأساس، أكمل مسار Docker بالعربي. وإن كانت المشكلة مع منفذ أقل من 1024 على لينكس، فراجع حل Permission denied في لينكس.

📚 مصادر رسمية للتعمّق: التوثيق الرسمي لـ Docker

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

ما الفرق بين الرقمين في -p 3001:3000؟

الصيغة هي منفذ-المضيف:منفذ-الحاوية. الأيسر (3001) هو ما يُفتح على جهازك وتزوره بالمتصفح، والأيمن (3000) هو ما يستمع عليه التطبيق داخل الحاوية. التعارض دائمًا على الأيسر، فغيّره هو فقط؛ التطبيق داخل الحاوية لا يشعر بأي فرق.

أوقفت الحاوية القديمة، هل ما زالت تحجز المنفذ؟

لا. الحاوية المتوقفة (Exited) تحرّر منفذ المضيف فورًا، وتستطيع تشغيل حاوية جديدة على نفس المنفذ مباشرة. إذا ظهر الخطأ بعد الإيقاف فهناك حاوية أخرى تعمل فعلًا، أو أن الحاوية القديمة عادت للعمل وحدها بسبب سياسة إعادة تشغيل مثل --restart always بعد إعادة تشغيل Docker أو الجهاز.

حلّيت المشكلة لكن docker run يقول إن اسم الحاوية مستخدم، لماذا؟

حين يفشل docker run بسبب المنفذ تبقى الحاوية التي أُنشئت بحالة Created. إن كنت تستخدم --name فأي محاولة ثانية بنفس الاسم تعطي Conflict. The container name is already in use. احذفها بـ docker rm <الاسم> ثم أعد التشغيل، أو شغّل بـ --rm من البداية.

على ويندوز تقول الرسالة Ports are not available مع أن لا شيء يستخدم المنفذ، لماذا؟

على Docker Desktop بويندوز قد يكون المنفذ داخل نطاق يحجزه النظام نفسه، فتظهر رسالة فيها An attempt was made to access a socket in a way forbidden by its access permissions. اعرض النطاقات المحجوزة بالأمر netsh interface ipv4 show excludedportrange protocol=tcp واختر منفذًا خارجها.

اقرأ أيضًا

تصفّح كل المقالات في المدوّنة، أو ابدأ التعلّم من المسارات و خرائط الطريق.