Not able to do a request to 127.0.0.1:8000 when running Streamlit on my machine launching it with a dockerFile

Viewed 1255

I have a streamlit application (localhost:8501) and an API (127.0.0.1:8000).

My streamlit application tries to access the API.

It works well when I launch the command to start "streamlit". But when streamlit is in a Docker container, I'm not able to access the URL. I have this error:

ConnectionError: HTTPConnectionPool(host='127.0.0.1', port=8000): Max retries exceeded with url: /predict (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f2a5ebae090>: Failed to establish a new connection: [Errno 111] Connection refused'))

This is my dockerfile:

FROM tiangolo/uvicorn-gunicorn:python3.7

ENV PYTHONPATH .

RUN mkdir /streamlit

COPY requirements.txt /streamlit

WORKDIR /streamlit

RUN pip install -r requirements.txt

COPY . /streamlit

EXPOSE 8501

CMD ["streamlit", "run", "web/source/web_api.py"]

And the commands I launch:

docker build --tag web_streamlit.
docker run --publish 8501:8501 --detach --name web_streamlit_container web_streamlit
3 Answers

I'm able to access localhost:8501. Inside I have a streamlit application that is unable to reach localhos:8000 which is another service.

To access service that is running on you have special DNS for mac and window.

host.docker.internal, which resolves to the internal IP address used by the host.

So replace localhost:8000 with host.docker.internal:8000

special DNS for mac and window

or if you Linux then set host to resolve the special DNS for your self.

docker run --publish 8501:8501 -it --rm --add-host="host.docker.internal:192.168.9.100" --name web_streamlit_container  web_streamlit

Where 192.168.9.100 is the host IP that you can get using ifconfig in linux.

So you have flexible DNS that will work all platform Linux,window and mac you do not need to modify code.

If you try to ping localhost from the container, the container will ping itself :)
If you want to reach a service that's running on the host itself, from the container, you need to fetch the IP of your docker0 interface:

On your host machine: run ip addr show docker0 to find it

neo@neo-desktop:~$ ip addr show docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:33:70:c8:74 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:33ff:fe70:c874/64 scope link 
       valid_lft forever preferred_lft forever

Fetch the IP (172.17.0.1 in my example) and use 172.17.0.1:8000 to reach your API form the continer.
PS: works on Linux. If you run Docker on Win or Mac, you need to do something else.

Technical overview of your problem & quick fix ☑️

__

Lets assume you have 2 docker images

1st image : Fastapi or any other API backend wrapped using Docker.

2nd image : Streamlit Frontend wrapped using Docker

Now , when you request API from streamlit docker to another docker eg (localhost://predict) it will not work.

Beacuse you are requested API current localhost to same docker localhost and its pointing to itself.

So you need to change that localhost present in your streamlit script to required API host (means another docker IP)

To finding that IP hit following command :-

ip addr show docker0 

It will give you ip address something like 172.17.0.1/16.

Now you have change your streamlit localhost request url to ,

http://172.17.0.1/

Then build the streamlit docker again.

docker build -t frontend: version-1

Now run the streamlit docker by,

docker run --rm -it -p 8501/8501/tcp frontend:version-1

Done ✅

Related