2025, Nov 06 15:01

Dash игнорирует HOST в Conda: причины и решения

Разбираем, почему Dash при наличии CONDA_PREFIX игнорирует HOST и слушает 127.0.0.1. Решения: host=0.0.0.0 в run или удалить CONDA_PREFIX перед импортом.

Приложения Dash часто используют переменные окружения для настройки. Распространённое ожидание: если задать HOST=0.0.0.0, сервер по умолчанию будет слушать все интерфейсы. Однако в некоторых окружениях приложение упорно привязывается к 127.0.0.1, хотя значение PORT учитывается. Разбираемся, почему так происходит и как это аккуратно исправить.

Минимальный пример, воспроизводящий проблему

import os
import dash
from dash import html
svc = dash.Dash(__name__)
svc.layout = html.Div("Hello Dash!")
print(f'{os.environ["HOST"]=}')
svc.run()

Документация Dash утверждает, что сервер должен учитывать HOST, если вы явно не передаёте параметр host:

host

IP-адрес хоста, на котором запускается приложение; по умолчанию — "127.0.0.1"; env: HOST

Но даже когда в окружении задано HOST=0.0.0.0, приложение может продолжать работать на 127.0.0.1, если явно не переопределить это в коде.

Что на самом деле происходит и почему

Dash намеренно игнорирует HOST, когда обнаруживает запуск в окружении, управляемом Conda (в os.environ присутствует CONDA_PREFIX). Такое поведение появилось при решении проблемы #3069 и было внесено в PR #3130. Причина в том, что некоторые активаторы Conda выставляют некорректное имя хоста (например, x86_64-conda-linux-gnu), из‑за чего ломается привязка сокета во Flask. Чтобы избежать этого сценария, Dash игнорирует HOST при наличии CONDA_PREFIX.

Практические способы решения

Если нужно, чтобы приложение слушало 0.0.0.0, самый простой путь — передать host явно из переменной окружения. Так вы сохраняете внешнюю конфигурацию и одновременно фиксируете поведение в коде.

import os
import dash
from dash import html
svc = dash.Dash(__name__)
svc.layout = html.Div("Hello Dash!")
env_host = os.environ.get("HOST", "127.0.0.1")
svc.run(host=env_host)

Есть и другой вариант: если вы хотите, чтобы Dash автоматически учитывал HOST, уберите CONDA_PREFIX до импорта dash — тогда защитная проверка не сработает.

import os
if "CONDA_PREFIX" in os.environ:
    del os.environ["CONDA_PREFIX"]
import dash
from dash import html
svc = dash.Dash(__name__)
svc.layout = html.Div("Hello Dash!")
print(f'{os.environ["HOST"]=}')
svc.run()

Так переменная окружения будет учтена ровно так, как описано в документации.

Почему это важно

При развёртывании Dash в контейнерах или оркестраторах привязка к 0.0.0.0 часто необходима, чтобы сервис был доступен извне. Ситуация, когда PORT соблюдается, а HOST игнорируется, сбивает с толку и тратит время на отладку. Понимание механизма с CONDA_PREFIX объясняет расхождение и помогает сделать конфигурацию предсказуемой.

Выводы

Если требуется конкретный адрес привязки, передавайте его явно в run — это однозначно и устойчиво к различным окружениям. Если вы полагаетесь на значения по умолчанию из переменных и работаете в контексте Conda, уберите CONDA_PREFIX до импорта dash, чтобы HOST учитывался. За подробностями и обоснованием такой проверки см. задачу Dash #3069 и PR #3130.

Статья основана на вопросе на StackOverflow от mckbrd и ответе пользователя Salt.