Cannot expose simple API using Docker container and FastAPI - python

I have a simple API with the following tree structure:
.
├── api
│   ├── fast.py
│   └── __init__.py
├── Dockerfile
├── Makefile
└── requirements.txt
The contents of fast.py are as follows:
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn
app = FastAPI()
#app.get("/")
def index():
return {"greeting": "Hello world!!!!!!!!!!!!!!"}
#app.get("/predict")
def predict():
# create a datetime object from the user provided datetime
return {'cool': True}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
The contents of the Dockerfile are as follows:
FROM python:3.8.6-buster
COPY api /api
COPY requirements.txt /requirements.txt
RUN pip install -r requirements.txt
CMD uvicorn api.fast:app --host 0.0.0.0 --port $PORT
When I start the API on my localhost in my Windows machine using wsl, it works fine, and I can access my API:
# uvicorn api.fast:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [20733] using statreload
INFO: Started server process [20770]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:40446 - "GET / HTTP/1.1" 200 OK
However, when I try to access it from within a Docker container, I have issues. First I build the image as follows:
docker build --tag=docker_api_example .
then I run a container as follows:
docker run -it -e PORT=8000 -p 8000:8000 docker_api_example sh
The container opens up and I run the same uvicorn command again:
# uvicorn api.fast:app --reload
The process appears to start with no issues:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [8] using statreload
INFO: Started server process [10]
INFO: Waiting for application startup.
INFO: Application startup complete.
However, when I navigate to http://127.0.0.1:8000 on my browser I get an error:
Why does this occur and how can I fix it?

Related

chose a specific python file to run in Fast API

I have 2 files in a folder named "pyproj"
main.py
post.py
folder path image
whenever I run the localhost with uvicorn, main.py is only shown in the local host browser.
In post.py I have the app instance as "app", so I run the uvicorn in terminal as
uvicorn main:app --reload
In post.py I have the app instance as "app2", so I run the uvicorn in terminal as
uvicorn post:app2 --reload
no matter what code I run from the above I can see only the main.py's paths. Can someone help with this.

Docker containers not communicating between each others using fastapi and requests module on windows

I've two apps- app1 and app2. When I call app1 using fast API, it calls app2 through fast API and returns the response from app2 to app1. Then app1 returns the response it got from app2. Both apps are working fine without docker. When I containerized both apps using docker-compose, they can't communicate but both are running. But I can access both containers using their APIs. I have also tried turning off my firewall, still not working. I'm using docker desktop on windows 10. Can anyone tell me/give me the fix, please? I'm exhausted trying different fixes. Thanks in advance.
Here are my codes:
App1:
#App1
from fastapi import FastAPI, UploadFile,File, Form
from fastapi.responses import FileResponse
import requests
import uvicorn
app = FastAPI()
#app.get("/")
def read_root():
response = requests.get('http://localhost:81/')
#f = urllib.request.urlopen('http://localhost:81/')
return {"response from app2":response.text}
App1 Dockerfile:
FROM python:3.7
WORKDIR /testset
COPY main.py .
COPY . .
RUN pip install fastapi uvicorn requests
App2:
#App2
from fastapi import FastAPI, File, UploadFile, HTTPException
import uvicorn
app = FastAPI()
#app.get('/')
def prediction_route():
f=2*5
return f
App2 Dockerfile:
FROM python:3.7
WORKDIR /var/www/html
COPY main.py .
COPY . .
RUN pip install fastapi uvicorn requests
docker-compose.yml
version: '3'
services:
app1:
container_name: App1_tx
build: ./app1/
restart: always
volumes:
- .:/testset
ports:
- "80:80"
command: uvicorn app1.main:app --reload --host 0.0.0.0 --port 80
depends_on:
- app2
app2:
container_name: App2_rx
build: ./app2/
restart: always
volumes:
- .:/var/www/html
ports:
- "81:81"
command: uvicorn app2.main:app --reload --host 0.0.0.0 --port 81
The Error response i get:
INFO: Will watch for changes in these directories: ['/testset']
INFO: 172.18.0.1:39980 - "GET / HTTP/1.1" 500 Internal Server Error
INFO: 172.18.0.1:39976 - "GET /favicon.ico HTTP/1.1" 404 Not Found
INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit)
INFO: Started reloader process [1] using statreload
INFO: Started server process [8]
INFO: Waiting for application startup.
INFO: Application startup complete.
ERROR: Exception in ASGI application
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 175, in _new_conn
(self._dns_host, self.port), self.timeout, **extra_kw
File "/usr/local/lib/python3.7/site-packages/urllib3/util/connection.py", line 96, in create_connection
raise err
File "/usr/local/lib/python3.7/site-packages/urllib3/util/connection.py", line 86, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
When you work with docker-compose services use their service name rather than localhost.
Thus, change your line in app1 from:
response = requests.get('http://localhost:81/')
to:
response = requests.get('http://app2:81/')

Unable to run Python flask app in different port using docker-compose

I am running Flask application in Python using docker-compose. I am able to run the Flask app using 5000 port. I am trying to run it on 6000 besides another Flask app running on 5000. But I am unable run it on 6000 port. Any help would be appreciated.
docker-compose.yml
version: '3.8'
services:
web:
build: ./web
ports:
- "6000:5000"
app.py
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Dockerfile:
FROM python:3
COPY . /app
WORKDIR /app
RUN pip install -U pip
RUN pip install -r requirements.txt
ENTRYPOINT ["python"]
CMD ["app.py"]
requirements.txt
Flask==1.1.1
Port 6000 is listening. I am able to get a connection succeeded by executing nc command with host and port.
I am unable to run the app on port 6000.
I got the following when I hit http://#{HOST_IP}:6000 in browser
This site can’t be reached
The web page at http://#{HOST_IP}:6000/ might be temporarily down or it may have moved permanently to a new web address.
6000 is unsafe port that is why browser not allowing to access the application.
how-to-fix-err-unsafe-port-error-on-chrome-when-browsing-to-unsafe-ports
But you should not allow this port, just try to publish another port.
version: '3.8'
services:
web:
build: ./web
ports:
- "5001:5000"
For downvoter
Here is Github Repo to verify this
git clone https://github.com/Adiii717/dockerize-flask-app.git
cd dockerize-flask-app/
# this will not work in the browser
PORT=6000 docker-compose up
You haven't defined any routes. The app server has no idea what routes are available nor does it know what you want to return, so you need to specify that.
Here's a more complete version of app.py
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Please refer to the Flask tutorial for a minimal app.

Nginx reverse proxy on unix socket for uvicorn not working

Files:
# main.py:
from fastapi import FastAPI
app = FastAPI()
#app.get("/")
def read_root():
return {"Hello": "World"}
-
# nginx.conf:
events {
worker_connections 128;
}
http{
server {
listen 0.0.0.0:8080;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uvi.sock;
}
}
}
-
# Dockerfile
FROM python:3
COPY main.py .
RUN apt-get -y update && apt-get install -y htop tmux vim nginx
RUN pip install fastapi uvicorn
COPY nginx.conf /etc/nginx/
Setup:
docker build -t nginx-uvicorn:latest .
docker run -it --entrypoint=/bin/bash --name nginx-uvicorn -p 80:8080 nginx-uvicorn:latest
Starting uvicorn as usual:
$ uvicorn --host 0.0.0.0 --port 8080 main:app
Works - I can access http://127.0.0.1/ from my browser.
Starting uvicorn behind nginx:
$ service nginx start
[ ok ] Starting nginx: nginx.
$ uvicorn main:app --uds /tmp/uvi.sock
INFO: Started server process [40]
INFO: Uvicorn running on unix socket /tmp/uvi.sock (Press CTRL+C to quit)
INFO: Waiting for application startup.
INFO: Application startup complete.
If I now request http://127.0.0.1/ then:
Nginx: Responds with 502 Bad Gateway
uvicorn: Responds with WARNING: Invalid HTTP request received.
Hence a connection is established but something is wrong about the configuration.
Any ideas?
You are using the uwsgi module of nginx. Uvicorn exposes an asgi API. Therefore you should use a "reverse proxy" configuration instead of an uwsgi configuration.
You can get more info on the uvicorn documentation: https://www.uvicorn.org/deployment/#running-behind-nginx (see the proxy_pass line)

Unable to load python flask API with a docker container

I'm trying to learn Docker containers with APIs. I have created a simple Hello World python REST API with flask:
from flask import Flask
app = Flask(__name__)
#app.route("/")
def hello():
return "Hello World!"
if __name__ == '__main__':
app.run(host="127.0.0.1", debug=True, port=8080)
This works when I run the script and go to http://localhost:8080/
This is my Dockerfile:
# Use an official Python runtime as a parent image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /hello_world
# Copy the current directory contents into the container at /app
ADD . /hello_world
# Install any needed packages specified in requirements.txt
RUN pip install --trusted-host pypi.python.org -r requirements.txt
EXPOSE 8080
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "hello_world.py"]
requirements.txt:
Flask
My current directory contains Dockerfile, hello_world.py and requirements.txt.
I can successfully build the image with docker build -t hello_world ."
Running it with docker run -p 8080:8080 -t hello_world gives me the following output:
Serving Flask app "hello_world" (lazy loading)
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: on
* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 985-433-141
When I try going to http://127.0.0.1:8080/ I get the "Can't reach this page" error. Do you know what I'm doing wrong? Thank you.

Categories

Resources