Что делать, если не можешь обратиться к API из контейнера Docker?

«Что делать, если не можешь обратиться к API из контейнера Docker?» — вопрос из категории DevOps, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Проблема обычно связана с сетевыми настройками. Вот пошаговый план диагностики и решения:

  1. Проверьте работу API вне Docker: Убедитесь, что сервис запущен и доступен локально.

    curl http://localhost:5000/api/health
  2. Проверьте проброс портов: При запуске контейнера убедитесь, что порты проброшены корректно.

    # Запуск с пробросом порта хоста 5000 на порт контейнера 5000
    docker run -p 5000:5000 my-api-image

    В Dockerfile сервиса должен быть указан EXPOSE для нужного порта.

  3. Используйте правильный хост для связи между контейнерами:

    • Внутри одной сети 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')
  4. Проверьте сеть 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
  5. Используйте инструменты для отладки:

    • Зайдите в контейнер и проверьте доступность эндпоинта:
      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).