Search code examples
dockerflask

Docker Error : Could not import 'hello' , No such command 'uvicorn'


I am currently creating an application that links Flask and mysql and runs it simply with Docker Compose.

  1. Error import 'hello' in dockerfile

I'm not sure if problem number 1 is a Docker file problem or a hello.py problem.

If you run python hello.py rather than a Docker file, the server will run fine.

However, if you build with Docker Compose and check on Docker Desktop, you can confirm that the problem occurred. Below is the corresponding code.

enter image description here

hello.py

## 1
from db_module import db_connector

from flask import Flask

app = Flask(__name__)

@app.route('/', methods = ['GET', 'POST'])
def alarm():
    result = db_connector()    
    return result



if __name__ == "__main__":              
    app.run(host="0.0.0.0", port="8000")

db_module.py

import pymysql
from flask  import Flask


def db_connector():
    
  db = pymysql.connect(host='127.0.0.1', user='root', password='', db='mysql', 
  charset='utf8')

  cursor = db.cursor()


  sql = "select *from user"


  cursor.execute(sql)

  result = cursor.fetchall()

  db.close()

  return str(result)

Dockerfile

FROM python:3.8-slim

COPY . .

RUN pip3 install -r requirements.txt

WORKDIR /backend/app

ENV FLASK_APP=hello.py
EXPOSE 8000

CMD ["python", "-m","flask","uvicorn","run", "bash","--host=0.0.0.0","--port", "8000"]

docker-compose.yml

version: '3.8'

services:
 web:
 build: "./app"
 ports:
  - "8000:8000"
 db:
  image: mysql:8.0
  environment:
    MYSQL_ROOT_PASSWORD: ""
    ports:  
       - "80:80"
  volumes:
       - mysqldb:/var/lib/mysql



volumes:
  mysqldb:

2.no such cmmand 'unicorn'

Currently, "unicorn" is listed in the requirment.txt file, but I am not sure why no such command is displayed.

requirments.txt

Flask
mysql-connector
uvicorn

enter image description here


Solution

  • There are several problems here.

    First, as David Maze points out, you're installing things in the wrong place. You're installing files into the root of the container, but then changing to /backend/app, so none of the files are where python can find them.

    Secondly, your CMD syntax doesn't make any sense.

    Fixing both of those problems would look like this:

    FROM python:3.8-slim
    
    WORKDIR /backend/app
    COPY . .
    RUN pip3 install -r requirements.txt
    
    EXPOSE 8000
    
    CMD ["uvicorn", "--host=0.0.0.0","--port", "8000", "hello:app"]
    

    To make things more efficient, you should install requirements.txt and perform package installation first:

    FROM python:3.8-slim
    
    WORKDIR /backend/app
    COPY requirements.txt ./
    RUN pip3 install -r requirements.txt
    COPY . .
    
    EXPOSE 8000
    
    CMD ["uvicorn", "--host=0.0.0.0","--port", "8000", "hello:app"]
    

    At this point you have a container that will start, but you still have a problem: uvicorn is designed for use with async frameworks like FastAPI or Quartz; it doesn't work with Flask applications. You will see only errors if you try to access your app.

    You would either need to use something like gunicorn instead of uvicorn, or switch to using FastAPI instead of Flask.

    For example:

    FROM python:3.8-slim
    
    WORKDIR /backend/app
    COPY requirements.txt ./
    RUN pip3 install -r requirements.txt
    COPY . .
    
    EXPOSE 8000
    
    CMD ["gunicorn", "--bind=0.0.0.0", "--workers=4", "hello:app"]