5

i want to use docker to containerize nginx, fastapi and 2 streamlit apps. All 3 apps (fastapi, 2streamlit apps) do not interact with each other. Nginx should work as reverse-proxy for the 3 apps. For fastapi it is working. I can send rest-api requests to http://ip:80/twxservices . "twxservices" as endpoint is added in the app.py file and not in the nginxconfig.

The streamlit apps are not reachable through this http://ip:80/stream1 and http://ip:80/stream2 I get the error: 404: Not found

Thanks in advance for your help. Find below the filestructures and the config files. This is the filestructure and how the reverse-proxy should work:

enter image description here enter image description here

docker-compose file:


services:
  web:
    build:
      context: ./nginxfolder
      dockerfile: Dockerfile
    container_name: web
   
    ports:
      - 80:80
    networks:
      - my-network
    depends_on:
      - app

  app:
    build:
      context: ./twxservicesfolder
      dockerfile: Dockerfile
    container_name: app
 
    networks:
      - my-network
      
  spectrum:
    build:
      context: ./spectrumfolder
      dockerfile: Dockerfile
    container_name: spectrum

    networks:
      - my-network
      
  dgraph:
    build:
      context: ./dgraphfolder
      dockerfile: Dockerfile
    container_name: dgraph

    networks:
      - my-network
       
networks:
  my-network:
    driver: bridge

nginx config (default.conf):

upstream fastapi-backend {
    server app:8000;
}



    server {
        listen 80;
     

        location /  {
            proxy_pass http://fastapi-backend;
            
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
       
            proxy_redirect off;
            proxy_buffering off;
            client_body_buffer_size 100M;
            client_max_body_size 100M;
        }
        
        location /stream1 {
            proxy_pass http://spectrum:8501/stream1;
        }
        location ^~ /stream1/static {
            proxy_pass http://spectrum:8501/stream1/static/;
        }
        location ^~ /stream1/healthz {
            proxy_pass http://spectrum:8501/stream1/healthz;
        }
        location ^~ /stream1/vendor {
            proxy_pass http://spectrum:8501/stream1/vendor;
        }
        location /stream1/spectrum {
            proxy_pass http://spectrum:8501/stream1/spectrum;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }
        
        location /stream2 {
            proxy_pass http://dgraph:8503/stream2;
        }
        location ^~ /stream2/static {
            proxy_pass http://dgraph:8503/stream2/static/;
        }
        location ^~ /stream2/healthz {
            proxy_pass http://dgraph:8503/stream2/healthz;
        }
        location ^~ /stream2/vendor {
            proxy_pass http://dgraph:8503/stream2/vendor;
        }
        location /stream2/dgraph {
            proxy_pass http://dgraph:8503/stream2/dgraph;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }

    }

Dockerfile nginx container:

FROM nginx:latest

RUN rm /etc/nginx/conf.d/default.conf
COPY default.conf /etc/nginx/conf.d

Dockerfile streamlit app dgraph container:

FROM python:3.8

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

EXPOSE 8503
COPY app2.py /var/dashboard/app2.py
CMD streamlit run /var/dashboard/app2.py --server.address="0.0.0.0"  --server.port="8503" 

Dockerfile streamlit app spectrum container:

FROM python:3.8

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

EXPOSE 8501
COPY app1.py /var/dashboard/app1.py
CMD streamlit run /var/dashboard/app1.py --server.address="0.0.0.0" --server.port="8501" 

Dockerfile fastapi app twxservices container:

FROM python:3.8-slim-buster

COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .

ENV PYTHONUNBUFFERED 1

EXPOSE 8000
CMD ["uvicorn","app:app","--proxy-headers","--host","0.0.0.0","--forwarded-allow-ips","*"]
Alsen57
  • 133
  • 1
  • 8
  • maybe `location /` should be as last rule. – furas Nov 15 '21 at 21:00
  • do you know why that should be? – Alsen57 Nov 16 '21 at 07:05
  • I'm not sure if it has to be last but many tools (i.e.`virtual_host` in `Apache`, `routing` in `Flask` and `Django`) get first matching location/routing. I'm not sure if `location /` compare as `if / == http://ip:80/stream2:` or `if / in http://ip:80/stream2:` but method with `in` can match all URLs and also `http://ip:80/stream1` and `http://ip:80/stream2` can match to `location /` and it may run wrong application. I would add the shortest `location` as the last. And the longest at the beginning. – furas Nov 16 '21 at 14:09
  • I tried this and moved the location / of fastapi to the end but it has not helped. Still get the error 404: Not found – Alsen57 Nov 16 '21 at 15:32
  • can you connect directly `http://spectrum:8501/stream1` ? Maybe it should be without `stream1` - `http://spectrum:8501/` – furas Nov 16 '21 at 16:21
  • Hi i made it now to work. It is important to paste in the dockerfile of the streamlitcontainer the basepath argument. E.g. --server.baseUrlPath="spectrum" Then in nginx config it is enough when using following: `location /spectrum { proxy_pass http://spectrum1:8501/spectrum; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400` – Alsen57 Nov 17 '21 at 09:57
  • you could write it as answer with detailed description- it will be more readable and maybe it will help other people. And you can mark your answer as accepted, and few minutes later you can upvote your answer. – furas Nov 17 '21 at 10:24

1 Answers1

3

I made it work with these nginx config

    location /spectrum {
            proxy_pass http://spectrum1:8501/spectrum;
            proxy_http_version 1.1;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_read_timeout 86400;
        }

and this Dockerfile config for the streamlit app:

FROM python:3.8
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt

EXPOSE 8501
COPY app1.py /var/dashboard/app1.py
CMD streamlit run /var/dashboard/app1.py --server.address="0.0.0.0" --server.port="8501" --server.baseUrlPath="spectrum" --server.enableCORS=false --server.enableXsrfProtection=false
Alsen57
  • 133
  • 1
  • 8