Ответ
Проблема обычно связана с сетевыми настройками. Вот пошаговый план диагностики и решения:
-
Проверьте работу API вне Docker: Убедитесь, что сервис запущен и доступен локально.
curl http://localhost:5000/api/health -
Проверьте проброс портов: При запуске контейнера убедитесь, что порты проброшены корректно.
# Запуск с пробросом порта хоста 5000 на порт контейнера 5000 docker run -p 5000:5000 my-api-imageВ
Dockerfileсервиса должен быть указанEXPOSEдля нужного порта. -
Используйте правильный хост для связи между контейнерами:
- Внутри одной сети Docker: Обращайтесь по имени сервиса (из
docker-compose.yml) или имени контейнера. - С хоста на контейнер: Используйте
host.docker.internal(macOS/Windows) или IP-адрес моста Docker (обычно172.17.0.1в Linux).# Пример кода внутри контейнера для обращения к API на хосте import requests response = requests.get('http://host.docker.internal:5000/api/data')
- Внутри одной сети Docker: Обращайтесь по имени сервиса (из
-
Проверьте сеть Docker: Убедитесь, что контейнеры находятся в одной пользовательской сети.
# Создание сети и запуск контейнеров в ней docker network create my-app-network docker run --network my-app-network --name api-service -p 5000:5000 api-image docker run --network my-app-network --name consumer-service consumer-image # Теперь consumer-service может обратиться к api-service по имени # http://api-service:5000/api/data -
Используйте инструменты для отладки:
- Зайдите в контейнер и проверьте доступность эндпоинта:
docker exec -it my-container sh apk add curl # или apt-get install curl curl -v http://api-service:5000 - Проверьте логи контейнера на предмет ошибок подключения:
docker logs <container_id>. - Убедитесь, что на хосте не блокирует соединение брандмауэр (например,
ufwилиfirewalld).
- Зайдите в контейнер и проверьте доступность эндпоинта:
Ответ 18+ 🔞
А, ну это же классика, ёпта! Сидишь такой, всё по инструкции сделал, а оно не работает — волнение ебать! Сейчас разберёмся, что за пиздопроебибна с сетью приключилась.
Первым делом, чувак, выключи эту свою докерную магию и проверь, а жив ли вообще твой API на голом железе. Запусти его локально и ткни в него палкой:
curl http://localhost:5000/api/health
Если в ответ тишина и мрак — значит, проблема не в докере, а в самом сервисе. Он, блядь, мог накрыться медным тазом ещё до погружения в контейнер. Почини сначала его.
Допустим, локально всё летает. Тогда следующий шаг — смотрим на проброс портов. Ты же не забыл, как запускал контейнер? Вот эта штука -p 5000:5000 — это священный ритуал, без него нихуя не заработает. Это как сказать системе: «Слушай, всё, что прилетает на 5000-й порт моего компьютера, засунь в этот самый порт у контейнера». И в Dockerfile тоже должен быть EXPOSE 5000, чтобы все знали, куда стучаться.
А вот теперь самое интересное — общение между контейнерами. Тут у многих мозг вскипает. Запоминай раз и навсегда: изнутри контейнера localhost — это он сам, а не твой компьютер!
Представь, ты в своей квартире (контейнере). Кричишь «Вася!» — откликнется твой сосед по квартире, а не парень с пятого этажа. Так и тут. Если твоему consumer-контейнеру нужно достучаться до api-контейнера, он должен звать его по имени.
- Если используешь
docker-compose.ymlи там прописаны сервисыapiиconsumer, то из контейнераconsumerстучись наhttp://api:5000. Всё, точка. - Если запускаешь вручную, создай общую сеть, посели их туда и общайся по имени контейнера.
А если нужно из контейнера достучаться до сервиса, который крутится на твоём основном компьютере (например, локальная база данных), тогда нужен специальный пароль. На Windows и macOS это host.docker.internal. На линуксе придётся выяснять IP-адрес моста Docker (часто 172.17.0.1).
# Пример кода внутри контейнера для обращения к API на хосте
import requests
response = requests.get('http://host.docker.internal:5000/api/data')
Если ничего не помогает — время для тяжёлой артиллерии. Залезай внутрь проблемного контейнера и смотри, что он там видит.
docker exec -it my-container sh
apk add curl # или apt-get install curl
curl -v http://api-service:5000
Опция -v покажет всю подноготную: идёт ли соединение вообще, какая ошибка. А ещё не забудь глянуть логи: docker logs <container_id> — там может быть написано что-то вроде «connection refused», и сразу станет понятно, куда копать.
И последнее, ядрёна вошь: проверь, не стоит ли у тебя на хосте брандмауэр, который режет все соединения. Особенно на линуксе с его ufw — он такой хитрая жопа, может всё разрешать локально, но блокировать трафик между сетями докера.