Nginx resolver в Docker: обновить IP сервиса

Категория: Nginx · Обновлено:

По умолчанию Nginx разрешает имя из proxy_pass один раз при старте и запоминает IP. В Docker контейнер сервиса может пересоздаться с другим адресом, и старый Nginx начнёт отдавать 502 до перезагрузки. Решение — встроенный DNS Docker и proxy_pass через переменную: тогда имя разрешается во время запроса.

Разрешать имя сервиса при каждом запросе

Текст
server {
    listen 80;
    resolver 127.0.0.11 valid=10s ipv6=off;
    resolver_timeout 2s;

    set $api http://api:8000;

    location / {
        proxy_pass $api;
        proxy_set_header Host $host;
    }
}

127.0.0.11 — адрес встроенного DNS-сервера Docker; он работает для контейнеров в пользовательской сети, где доступно имя сервиса api. Параметр valid=10s ограничивает время кеширования ответа, ipv6=off убирает лишние AAAA-запросы, если IPv6 в сети не настроен. resolver_timeout не даёт запросу висеть при недоступном DNS.

Без переменной proxy_pass http://api:8000; Nginx пытается разрешить имя при загрузке конфигурации и завершается с ошибкой host not found in upstream, если сервис ещё не запущен. С переменной $api проверка откладывается до запроса, поэтому порядок запуска контейнеров перестаёт быть критичным.

Учтите, что resolver не читает /etc/hosts и не использует системный resolver автоматически: адрес DNS нужно указать явно. В Docker Compose это 127.0.0.11, в Kubernetes — DNS кластера, на хосте — локальный или публичный resolver. Слишком маленький valid увеличивает число DNS-запросов; 10–30 секунд обычно достаточно.

При proxy_pass с переменной Nginx передаёт исходный URI без отдельного rewrite. Если нужно изменить путь, соберите адрес явно, например proxy_pass $api$request_uri;, и проверьте, что схема и порт входят в переменную. Для keepalive к бэкенду переменная не даёт использовать статический upstream; в таком случае применяйте динамическое разрешение через поддерживаемый вашей версией механизм или перезагружайте Nginx после изменения адресов.

Документация: ngx_http_core_module: resolver, Docker DNS.