Как наладить определение города в локальном Docker и нормально тестировать GeoIP
На локальной машине GeoIP почти всегда ведёт себя иначе, чем на боевом сервере. На проде приложение видит внешний IP посетителя и может определить город. В Docker локально приложение чаще всего получает внутренний адрес контейнера, адрес прокси или вообще пустое значение. Из-за этого город не определяется, всегда показывается один и тот же вариант или срабатывает запасное значение.
В этой статье разберём, как понять источник проблемы, как настроить локальное окружение без правок бизнес-логики сайта и как тестировать разные города без хаоса.
Почему в локальном Docker GeoIP работает не так, как на бою
Обычно цепочка на боевом сервере выглядит так:
- Пользователь открывает сайт со своим внешним IP.
- Балансировщик или веб-сервер передаёт этот IP дальше.
- PHP получает реальный адрес пользователя.
- Модуль GeoIP определяет город по этому адресу.
Локально эта цепочка ломается. Приложение видит не внешний IP, а один из таких вариантов:
- внутренний адрес Docker-сети;
- адрес локального reverse proxy;
-
127.0.0.1; - пустое значение, если заголовки не проброшены.
Для GeoIP это принципиально. Если приложению не передан внешний IP, модуль определения местоположения просто не может отработать так же, как на боевом сервере.
Типичные симптомы
- на локалке всегда определяется один и тот же город;
- у нового пользователя показывается город по умолчанию;
-
GeoIpManager::getCityName()возвращаетnull; - при ручной подмене IP в одном месте результат не меняется из-за cookie;
- после смены IP на странице остаётся старый город, потому что он уже записан в клиентские данные.
Что проверить в первую очередь
Перед любыми правками полезно быстро разделить проблему на три части:
- Приложение вообще получает IP или нет.
- GeoIP умеет определить город по этому IP или нет.
- Поверх результата не лежит cookie с городом, записанная ранее.
Если не сделать эту проверку сразу, легко начать чинить модуль GeoIP, хотя реальная причина окажется в reverse proxy или в старой cookie.
Минимальная схема для локального теста
Для локальной разработки удобнее всего использовать такую схему:
- сайт работает в Docker;
- перед PHP пробрасывается
X-Forwarded-For; - если заголовок не задан вручную, можно использовать один тестовый внешний IP по умолчанию;
- для проверки конкретного города заголовок подставляется вручную через браузерное расширение,
curlили локальный proxy.
Это позволяет:
- не трогать прикладной код ради локальной отладки;
- повторяемо воспроизводить разные города;
- быстро отличать проблему окружения от проблемы в шаблоне или компоненте.
Как правильно пробрасывать IP в локальном nginx
Если приложение определяет город через $_SERVER и доверяет X-Forwarded-For, локально достаточно передать этот заголовок до PHP.
Пример идеи для конфигурации:

Top comments (0)