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
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
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