skip to Main Content

I want to deploy a worker (FastApi) and a web (react) container to Heroku using docker-compose. Running locally, everything works. But on Heroku, the frontend cannot reach the backend.

Dockerfile.worker

FROM tiangolo/uvicorn-gunicorn-fastapi:python3.7

WORKDIR /app
COPY app .
COPY requirements.txt ./requirements.txt

ENV IS_IN_DOCKER=true

RUN pip3 install -r requirements.txt
RUN pip3 install -r ./custom_model/custom_requirements.txt

CMD uvicorn main:app --host 0.0.0.0 --port 8800

Dockerfile.web

# pull official base image
FROM node:13.12.0-alpine

# set working directory
WORKDIR /app

# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH

# install app dependencies
COPY package.json ./
COPY package-lock.json ./
RUN npm install --silent
RUN npm install [email protected] -g --silent

# add app
COPY . ./

# start app
CMD ["npm", "start"]

docker-compose.yml (using the Port Env variable from heroku for the frontend, locally i have a .env File with PORT=80)

version: '3.7'
services:
  ml-starter-frontend:
    depends_on:
      - ml-starter-backend
    container_name: ml-starter-frontend
    build:
      context: ./frontend
      dockerfile: Dockerfile.web
    ports:
      - '${PORT}:3000'
    restart: always
   ml-starter-backend:
     container_name: ml-starter-backend
     build:
       context: ./backend
       dockerfile: Dockerfile.worker
     restart: always

setupProxy.js in React src

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
    app.use(
        '/api/*',
        createProxyMiddleware({
            target: 'http://ml-starter-backend:8800',
            changeOrigin: true,
        })
    );
};

Call in React frontend to backend

export const getConfiguration = () => async (dispatch) =>{

    const {data} = await axios.get('/api/configs')
    dispatch({type: GET_CONFIGURATION, payload: data })

}

Running locally the call works:
Locally

Deployment to heroku:

heroku container:push --recursive --app {appName}
heroku container:release worker --app {appName}
heroku container:release web --app {appName}

Frontend cannot reach backend:
Heroku

Heroku Worker (FastAPI) log

2021-04-09T10:10:55.322684+00:00 app[worker.1]: INFO:     Application startup complete.
2021-04-09T10:10:55.325926+00:00 app[worker.1]: INFO:     Uvicorn running on http://0.0.0.0:8800 (Press CTRL+C to quit)

Heroku Web (React) Log

2021-04-09T10:11:21.572639+00:00 app[web.1]: [HPM] Proxy created: /  -> http://ml-starter-backend:8800

…..

2021-04-09T10:25:37.404622+00:00 app[web.1]: [HPM] Error occurred while trying to proxy request /api/configs from {appName}.herokuapp.com to http://ml-starter-backend:8800 (ENOTFOUND) (https://nodejs.org/api/errors.html#errors_common_system_errors)

If possible i would like to avoid nginx as I already spent 2 hours trying to make it work with proxies in the prod build. Does anybody have experience with heroku and docker-compose and could give me a hint how to fix this?

2

Answers


  1. Chosen as BEST ANSWER

    For everybody with a similiar problem.. Actually i ended up with a workaround.. I made a dockerfile containing the backend and frontend.. and deployed it to Heroku as a web app..

    During my search i discovered, that Heroku workers are not really suitable in a HTTP scenario. If I understood it right, they are meant for reading messages from a queue.. https://devcenter.heroku.com/articles/background-jobs-queueing


  2. Yup, I did something like what Loki34 did too. My approach was to run npm run build, then have FastAPI serve these build files. And like what Loki34 says, this is a workaround approach, meaning it’s probably not the best approach out there when it comes to deploying frontend and backend in Docker containers. Anyway, those who are curious about how I did it can check out this app that I did: https://github.com/yxlee245/app-iris-ml-react-fastapi

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