skip to Main Content

I am trying to deploy a fast API todo app onto Heroku by container registry. When I build the docker image and run it in my local. I am able to access my swagger in http://localhost:8001/docs. But I am not able to access when I deployed to heroku and I am getting this error :
Error: Exec format error

Here is my main.py

from fastapi import FastAPI,Depends
from fastapi.middleware.cors import CORSMiddleware
from db.db import get_db
from bson.objectid import ObjectId
from models.todo import Todo

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/")
def root():
    return {"message": "Hello World"}

@app.get("/api/todo",response_model=Todo)
async def get_todo(db=Depends(get_db)):
    data = await db.todo.find()
    result: Todo = Todo(**data)
    return result

@app.get("/api/todo/{todo_id}",response_model=Todo)
async def get_todo(todo_id: str,db=Depends(get_db)):
    data = await db.todo.find_one({"_id": ObjectId(todo_id)})
    result: Todo = Todo(**data)
    return result

@app.post("/api/todo")
async def create_todo(db=Depends(get_db),payload:Todo=None):
    result  = await db.todo.insert_one(payload.dict())
    return {"message": "Todo created successfully", "todo_id": str(result.inserted_id)}

@app.put("/api/todo/{todo_id}")
async def update_todo(todo_id: str,db=Depends(get_db),payload:Todo=None):
    result  = db.todo.update_one({"_id": ObjectId(todo_id)}, {"$set": payload.dict()})
    return {"message": "Todo updated successfully", "todo_id": str(result.inserted_id)}

@app.delete("/api/todo/{todo_id}")
async def delete_todo(todo_id: str,db=Depends(get_db)):
    result = db.todo.delete_one({"_id": ObjectId(todo_id)})
    return {"message": "Todo deleted successfully", "todo_id": str(result.inserted_id)}

and my Dockerfile

FROM python:3.8
WORKDIR /code
COPY requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code/
# EXPOSE 8000
RUN chmod +x run.sh
ENTRYPOINT ["/bin/bash", "-c" ,"./run.sh"]

I tried using CMD instead of ENTERYPOINT did not work. I also tried using

CMD ["uvicorn", "main:app","--proxy-headers", "--host", "${HOST}", "--port", "${PORT}"]

run.sh

#!/bin/sh

export APP_MODULE=${APP_MODULE-main:app}
export HOST=${HOST:-0.0.0.0}
export PORT=${PORT:-8001}

# run gunicorn
gunicorn --bind $HOST:$PORT "$APP_MODULE" -k uvicorn.workers.UvicornWorker 

requirements.txt

fastapi
uvicorn
motor
gunicorn

2

Answers


  1. You are building locally (Mac?) the image on a platform which is not compatible with Heroku (linux/amd64)
    Set the platform as you build/push the image to the Heroku registry

    DOCKER_DEFAULT_PLATFORM=linux/amd64 heroku container:push web -a myapp
    

    You can also set the DOCKER_DEFAULT_PLATFORM as env variables (to avoid setting it everytime – note all images would be linux/amd64)

    export DOCKER_DEFAULT_PLATFORM=linux/amd64
    
    Login or Signup to reply.
  2. Try using a heroku.yml file instead of CMD to start the server when it’s deployed to heroku.

    I was unable to connect to my server until I switched to the heroku.yml.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search