خلاصه سریع: اگر کانتینر 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 روی زیرساخت مستقل نیز میتوانید پلنهای سرور مجازی وانسرور را بررسی کنید.