Docker: нет доступа к сети из контейнера — причины и решение
Приложение в контейнере не может выйти в интернет или достучаться до соседнего сервиса: Docker нет доступа к сети из контейнера. Проблема выглядит пугающе, но обычно сводится к одной из нескольких причин: не работает DNS, отключён форвардинг пакетов, мешает файрвол или контейнеры в разных сетях не видят друг друга. Разберём, как быстро локализовать барьер и вернуть контейнеру связь.
Содержание
- Первое действие: определите, что именно не работает
- Причина 1: не работает DNS внутри контейнера
- Причина 2: отключён форвардинг IP
- Причина 3: мешает файрвол или его правила сброшены
- Причина 4: контейнеры в разных сетях не видят друг друга
- Как проверить, что связь восстановлена
- Профилактика: стабильная сеть контейнеров
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Первое действие: определите, что именно не работает
«Нет сети» — размытая формулировка. Сузьте её парой проверок изнутри контейнера: различить проблему DNS и проблему маршрутизации критически важно, потому что лечатся они по-разному.
docker exec -it имя_контейнера sh
ping -c2 8.8.8.8
ping -c2 google.com
Если ping 8.8.8.8 по IP работает, а ping google.com по имени — нет, то сеть есть, а сломан DNS (разрешение имён). Если не проходит даже пинг по IP — проблема в маршрутизации, форвардинге или файрволе. Если внешний интернет работает, но не достучаться до другого контейнера — дело в сетях Docker и разрешении имён между контейнерами. Эти три сценария — DNS, маршрутизация, межконтейнерная связь — и есть три ветки диагностики. Определив свой случай, вы сразу переходите к нужному разделу и не тратите время на неверные правки.
Причина 1: не работает DNS внутри контейнера
Если IP пингуется, а имена не резолвятся — сломан DNS. Контейнер использует DNS-настройки от демона Docker, и если на хосте проблемы с DNS или заданы нерабочие серверы, контейнеры их наследуют. Проверьте, какой DNS видит контейнер:
docker exec -it имя_контейнера cat /etc/resolv.conf
Если там пусто или нерабочий адрес, задайте контейнеру рабочие DNS-серверы явно — при запуске или в настройках демона:
docker run --dns 8.8.8.8 --dns 1.1.1.1 myimage
Для постоянного решения пропишите dns в /etc/docker/daemon.json и перезапустите Docker — тогда все контейнеры получат рабочие серверы. Частая причина поломки DNS — конфликт с локальным резолвером хоста (например, systemd-resolved) или VPN на сервере, меняющий DNS. Убедитесь, что сам хост корректно резолвит имена; если хост не может — не сможет и контейнер. DNS — самая частая причина «нет сети», когда по IP всё работает.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под DockerПричина 2: отключён форвардинг IP
Docker маршрутизирует трафик контейнеров через хост, и для этого в ядре должен быть включён форвардинг пакетов (ip_forward). Если он выключен — например, после ручной правки sysctl или на некоторых образах ОС, — контейнеры не могут выйти в интернет вообще, даже по IP. Проверьте состояние форвардинга на хосте:
sysctl net.ipv4.ip_forward
Если значение 0 — форвардинг отключён, и это ломает исходящую сеть контейнеров. Включите его немедленно и закрепите, чтобы сохранялось после перезагрузки:
sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
Docker обычно включает форвардинг сам при старте, но настройки безопасности, кастомные образы или другой софт могут его сбросить. После включения перезапустите Docker, чтобы он корректно восстановил правила маршрутизации. Отключённый ip_forward — классическая причина, когда контейнеры «полностью без сети», и лечится она одной строкой.
Причина 3: мешает файрвол или его правила сброшены
Docker управляет сетью контейнеров через правила iptables, и если файрвол настроен агрессивно или его правила были сброшены/перезаписаны сторонним инструментом, связь контейнеров ломается. Частый сценарий — вы применили свой набор правил или перезапустили файрвол, и он затёр цепочки Docker. Проверьте, на месте ли правила Docker:
iptables -L -n | grep -i docker
Если цепочек Docker нет или они пусты, а раньше сеть работала — правила сброшены. Самый надёжный способ восстановить их — перезапустить Docker, он пересоздаёт свои правила при старте:
systemctl restart docker
На будущее: не сбрасывайте iptables вслепую на сервере с Docker и настраивайте файрвол так, чтобы он не конфликтовал с цепочками Docker (например, аккуратно с UFW, который известен трениями с Docker). Если используете внешний файрвол провайдера, убедитесь, что он не режет нужный трафик. Конфликт файрвола — частая причина, когда сеть «вдруг» пропала после изменений в безопасности хоста.
Причина 4: контейнеры в разных сетях не видят друг друга
Если внешний интернет работает, но контейнеры не достукиваются друг до друга — они, скорее всего, в разных Docker-сетях или обращаются по неверному имени. Контейнеры видят друг друга по имени сервиса только внутри одной пользовательской сети. Посмотрите, в каких сетях они находятся:
docker network ls
docker inspect имя_контейнера | grep -i networks -A10
Если контейнеры в разных сетях — подключите их к общей или опишите в одном compose-файле, где они по умолчанию попадают в одну сеть и резолвятся по имени сервиса. Важный нюанс: в дефолтной сети bridge разрешение по имени не работает — нужна пользовательская сеть (её создаёт compose или docker network create). Ещё частая ошибка — обращаться к соседнему сервису по localhost: внутри контейнера localhost это он сам, а не хост или другой контейнер. К соседу обращайтесь по имени сервиса, к хосту — по host.docker.internal (где поддерживается) или адресу шлюза. Правильная сеть и правильное имя решают межконтейнерную связь.
Как проверить, что связь восстановлена
После правок проверьте именно тот тип связи, что был сломан. Для внешнего доступа — пинг и резолв имени изнутри; для межконтейнерного — обращение к соседу по имени сервиса:
docker exec -it имя_контейнера sh -c "ping -c2 google.com; nc -zv имя_сервиса 5432"
Успешный резолв имени и открытый порт соседнего сервиса подтверждают, что и DNS, и маршрутизация, и межконтейнерная сеть в порядке. Если что-то снова не проходит — вернитесь к соответствующей ветке: по IP не идёт значит форвардинг или файрвол, имя не резолвится значит DNS, сосед недоступен значит сети. Проверка ровно того сценария, что чинили, экономит время и подтверждает, что проблема ушла по сути, а не замаскировалась.
Профилактика: стабильная сеть контейнеров
Чтобы сетевые проблемы не возвращались, придерживайтесь нескольких правил. Описывайте связанные сервисы в одном compose-файле — тогда они попадают в общую сеть и резолвятся по имени без ручной настройки. Не сбрасывайте iptables вслепую и настраивайте файрвол с учётом Docker, чтобы не затирать его цепочки. Держите на хосте рабочие DNS-серверы и, при необходимости, задайте их демону Docker явно в daemon.json. Убедитесь, что ip_forward включён и сохраняется после перезагрузки.
Помните ключевые принципы адресации: localhost внутри контейнера — это сам контейнер, к соседям обращаются по имени сервиса в общей сети, к хосту — через шлюз или специальное имя. Эти привычки снимают большинство сетевых вопросов ещё до их появления. А при отладке всегда начинайте с разделения «DNS или маршрутизация» через пинг по IP и по имени — это мгновенно направляет вас к правильной причине и превращает пугающее «нет сети» в конкретную и решаемую задачу.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США и РФ. Оплата картой РФ и по СБП.
Арендовать VPS под DockerОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Как понять, DNS сломан или маршрутизация?
Пингуйте изнутри контейнера сначала IP (ping 8.8.8.8), потом имя (ping google.com). Работает IP, но не имя — проблема в DNS. Не идёт даже IP — маршрутизация, форвардинг или файрвол.
Контейнеры не видят друг друга по имени. Почему?
Скорее всего они в дефолтной сети bridge, где нет разрешения по имени, или в разных сетях. Опишите их в одном compose или подключите к общей пользовательской сети — там имена сервисов резолвятся.
Сеть контейнеров пропала после настройки файрвола. Что делать?
Файрвол, вероятно, затёр цепочки iptables Docker. Перезапустите Docker (systemctl restart docker) — он пересоздаст правила. Впредь не сбрасывайте iptables вслепую на Docker-хосте.
Как оплатить сервер под Docker из России?
В MAATRIX — картой российского банка, через СБП, криптовалютой или токеном MAAT. Иностранная карта не нужна.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.