ESC را فشار دهید تا بسته شود

رفع مشکل DNS در Docker؛ چرا کانتینر دامنه‌ها را Resolve نمی‌کند؟

فهرست

خلاصه سریع: اگر کانتینر Docker به IPها دسترسی دارد اما نام دامنه‌ها را Resolve نمی‌کند، مشکل معمولاً از DNS داخل کانتینر، فایل /etc/resolv.conf میزبان، resolver لوپ‌بک مثل 127.0.0.1/127.0.0.53 یا تنظیم DNS در Docker daemon است. اول DNS میزبان و کانتینر را جداگانه تست کنید؛ سپس با --dns یک تست موقت بگیرید و فقط اگر مشکل تأیید شد، DNS پایدار را در /etc/docker/daemon.json تنظیم کنید.

سناریو: اینترنت داخل Docker هست، ولی DNS کار نمی‌کند

نشانه رایج این است که ارتباط شبکه برقرار است اما دستورهایی مثل apt update، curl example.com یا اتصال برنامه به یک hostname با خطاهایی مثل Temporary failure in name resolution، Could not resolve host یا Name or service not known شکست می‌خورند.

در Docker، کانتینرهای متصل به bridge پیش‌فرض معمولاً تنظیمات DNS میزبان را از /etc/resolv.conf می‌گیرند؛ در شبکه‌های سفارشی نیز Docker از DNS داخلی خودش برای نام سرویس‌ها استفاده می‌کند و درخواست‌های دیگر را به resolverهای بالادستی می‌فرستد. بنابراین قبل از تغییر تنظیمات باید مشخص کنیم خرابی در میزبان، daemon یا فقط یک کانتینر است.

مرحله ۱: اول ثابت کنید مشکل واقعاً DNS است

وضعیت کانتینرها را ببینید:

docker ps

داخل یک کانتینر آزمایشی ابتدا دسترسی IP و سپس DNS را جداگانه بررسی کنید:

docker run --rm alpine ping -c 3 1.1.1.1
docker run --rm alpine nslookup example.com

اگر تست IP موفق است ولی nslookup شکست می‌خورد، مسیر شبکه تا اینترنت برقرار است و باید روی DNS تمرکز کنید. اگر خود IP هم در دسترس نیست، ابتدا routing، firewall، forwarding یا شبکه Docker را بررسی کنید؛ تغییر DNS در آن حالت درمان اصلی نیست.

مرحله ۲: DNS میزبان را بررسی کنید

روی خود VPS یا سرور لینوکس اجرا کنید:

cat /etc/resolv.conf
getent hosts example.com

اگر میزبان هم نام دامنه را Resolve نمی‌کند، ابتدا DNS سیستم‌عامل را اصلاح کنید. Docker نمی‌تواند یک DNS خراب در Host را به‌صورت قابل‌اعتماد جبران کند.

به آدرس‌های loopback در resolv.conf دقت کنید؛ مثلاً:

nameserver 127.0.0.1

طبق مستندات Docker، resolver محلی روی loopback می‌تواند برای کانتینر مشکل‌ساز شود، چون 127.0.0.1 داخل namespace کانتینر به خود همان کانتینر اشاره می‌کند، نه به Host.

مرحله ۳: resolv.conf داخل کانتینر را با Host مقایسه کنید

docker run --rm alpine cat /etc/resolv.conf

برای کانتینر موجود:

docker exec -it CONTAINER_NAME cat /etc/resolv.conf

اگر شبکه سفارشی Docker استفاده می‌کنید، دیدن آدرس DNS داخلی Docker طبیعی است. مسئله مهم این است که آیا درخواست‌ها از آن resolver به DNS بالادستی می‌رسند یا نه.

مرحله ۴: با –dns تست موقت بگیرید

قبل از دست‌کاری تنظیمات سراسری Docker، یک کانتینر موقت را با DNS مشخص اجرا کنید:

docker run --rm --dns 1.1.1.1 alpine nslookup example.com

اگر DNS داخلی سازمان دارید، همان IP را جایگزین کنید. اگر این تست موفق شد ولی اجرای عادی شکست خورد، شواهد خوبی دارید که مشکل از DNS تحویلی به کانتینر یا resolver بالادستی Docker است.

نکته: برای سرویس‌هایی که باید hostnameهای داخلی شرکت را Resolve کنند، استفاده صرف از DNS عمومی مناسب نیست؛ DNS داخلی باید در دسترس کانتینر باشد.

مرحله ۵: DNS پایدار Docker daemon را تنظیم کنید

قبل از تغییر، از فایل فعلی نسخه پشتیبان بگیرید:

sudo cp -a /etc/docker/daemon.json /etc/docker/daemon.json.bak 2>/dev/null || true

فایل را باز کنید:

sudo nano /etc/docker/daemon.json

اگر فایل خالی است، نمونه زیر قابل استفاده است:

{
  "dns": ["1.1.1.1", "8.8.8.8"]
}

اگر daemon.json از قبل تنظیمات دیگری دارد، کل فایل را با نمونه بالا جایگزین نکنید؛ فقط کلید dns را با JSON معتبر به آبجکت موجود اضافه کنید.

مرحله ۶: قبل از Restart، کانفیگ را Validate کنید

یک اشتباه JSON می‌تواند باعث بالا نیامدن Docker daemon شود. قبل از Restart اجرا کنید:

sudo dockerd --validate --config-file=/etc/docker/daemon.json

در حالت صحیح باید پیام معتبر بودن فایل را ببینید. سپس وضعیت فعلی سرویس را ثبت و Docker را Restart کنید:

sudo systemctl status docker --no-pager
sudo systemctl restart docker
sudo systemctl status docker --no-pager

روی سرور Production توجه کنید که Restart کردن daemon می‌تواند روی کانتینرهای در حال اجرا اثر بگذارد؛ زمان مناسب نگهداری و سیاست restart سرویس‌ها را در نظر بگیرید.

مرحله ۷: بعد از اصلاح، DNS را Verify کنید

سه تست را انجام دهید:

docker pull hello-world
docker run --rm alpine nslookup example.com
docker run --rm alpine ping -c 3 example.com

اگر DNS داخلی دارید:

docker run --rm alpine nslookup internal.example.local

برای یک کانتینر واقعی نیز وضعیت DNS را بررسی کنید:

docker exec -it CONTAINER_NAME getent hosts example.com

اگر فقط Docker Compose مشکل DNS دارد

اگر سایر کانتینرها سالم‌اند و فقط یک سرویس Compose مشکل دارد، قبل از تغییر سراسری daemon می‌توانید DNS را برای همان سرویس تعریف کنید:

services:
  app:
    image: your-image
    dns:
      - 1.1.1.1
      - 8.8.8.8

سپس پیکربندی Compose را بررسی و سرویس را بازسازی کنید:

docker compose config
docker compose up -d

برای آشنایی با ساختار فایل و مدیریت چند سرویس، راهنمای آموزش Docker Compose روی سرور لینوکس را ببینید.

خطاهای رایج هنگام رفع DNS در Docker

۱. تغییر DNS وقتی مشکل اصلی Routing است

اگر ping 1.1.1.1 هم شکست می‌خورد، DNS تنها مشکل شما نیست. ابتدا مسیر شبکه، NAT، forwarding و firewall را بررسی کنید.

۲. قرار دادن 127.0.0.1 به‌عنوان DNS کانتینر

Loopback داخل کانتینر به خود کانتینر اشاره می‌کند. اگر DNS روی Host اجرا می‌شود، باید معماری شبکه و آدرس قابل دسترس آن برای کانتینر مشخص باشد.

۳. خراب کردن daemon.json

همیشه قبل از Restart از dockerd --validate استفاده کنید. تعریف هم‌زمان یک گزینه در daemon.json و flagهای startup نیز می‌تواند باعث Fail شدن daemon شود.

۴. استفاده از DNS عمومی برای hostname داخلی

DNS عمومی نام‌های داخلی سازمان را نمی‌شناسد. در این سناریو DNS داخلی را به Docker معرفی کنید و دسترسی شبکه کانتینر به آن را هم تست کنید.

Rollback: اگر Docker بعد از تغییر بالا نیامد چه کنیم؟

اگر بعد از تغییر daemon.json سرویس Fail شد، ابتدا لاگ را بخوانید:

sudo systemctl status docker --no-pager
sudo journalctl -u docker -n 100 --no-pager

سپس نسخه پشتیبان را برگردانید:

sudo cp -a /etc/docker/daemon.json.bak /etc/docker/daemon.json
sudo dockerd --validate --config-file=/etc/docker/daemon.json
sudo systemctl restart docker

اگر فایل پشتیبان وجود نداشت و تنها تغییر شما کلید DNS بوده، همان تغییر را با دقت حذف کنید، JSON را Validate و سپس daemon را Restart کنید.

چطور بفهمیم مشکل از DNS است یا خود Docker؟

ترتیب تشخیص ساده است: DNS روی Host → دسترسی IP داخل کانتینر → resolv.conf داخل کانتینر → تست موقت --dns → تنظیم پایدار daemon. این ترتیب جلوی تغییرات تصادفی و Restartهای غیرضروری را می‌گیرد.

اگر تازه چند سرویس را روی یک VPS کانتینری کرده‌اید، مقاله مدیریت داده کانتینرها با Docker Volume و Bind Mount نیز برای جلوگیری از از دست رفتن داده هنگام بازسازی کانتینر مفید است. برای اجرای سرویس‌های Docker روی زیرساخت مستقل نیز می‌توانید پلن‌های سرور مجازی وان‌سرور را بررسی کنید.

منابع فنی

Rate this post
اشتراک گذاری نوشته در:

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *