How to deploy react app in Elastic beanstalk in a docker platform using Travis CI? - reactjs

Environment health has transitioned from Ok to Severe. ELB processes are not healthy on all instances. ELB health is failing or not available for all instances.
I am deploying a react app in AWS using the docker platform. I am getting HEALTH-Severe issues when I deploy my app. I have also added custom TCP inbound rules in the EC2 instance (source-anywhere).
I am using free tier in AWS. The following is my Dockerfile.
FROM node:alpine as builder
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx
EXPOSE 80
COPY --from=builder /app/build /usr/share/nginx/html
My .travis.yml file:
language: generic
sudo: required
services:
- docker
before_install:
- docker build -t username/docker-react -f Dockerfile.dev .
script:
- docker run -e CI=true username/docker-react npm run test
deploy:
provider: elasticbeanstalk
region: us-east-2
app: "docker-react"
env: "DockerReact-env"
bucket_name: "my bucket-name"
bucket_path: "docker-react"
on:
branch: master
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
When I open my app I am getting 502 Bad Gateway error.

I had the same problem. After reading some of the documentation here I figured maybe docker-compose.yml is actually picked up first before anything. Deleting my docker-compose.yml (which I was only using locally) solved the issue for me.

Related

Deploy React Frontend, FastApi Backend with Docker-Compose on Heroku

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 react-scripts#3.4.1 -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?
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

elasticbeanstalk on the Docker platform: 502 Bad Gateway for the react app

I have a dummy react app deployed from Dockerfile.dev:
FROM node:alpine AS builder
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
RUN npm run build
FROM nginx
EXPOSE 80
COPY --from=builder /app/build /usr/share/nginx/html
which is deployed to elasticbeanstalk right after it is pushed to GitHub using TravisCI:
sudo: required
services:
- docker
before_install:
- docker build -t name/docker-react -f Dockerfile.dev .
script:
- docker run -e CI=true name/docker-react npm run test
deploy:
provider: elasticbeanstalk
region: 'us-east-1'
app: 'docker'
env: 'Docker-env'
bucket_name: 'elasticbeanstalk-us-east-1-709516719664'
bucket_path: 'docker'
on:
branch: main
access_key_id: $AWS_ACCESS_KEY
secret_access_key: $AWS_SECRET_KEY
The app is successfully deploying to EB but displays 502 Bad Gateway as soon as I access it (by clicking the app link in AWS EB). Enhanced health overview reports:
Process default has been unhealthy for 18 hours (Target.FailedHealthChecks).
Docker-env EC2 instance is running and after allowing all incoming connections to it I can connect just fine:
I can build my app using Dockerfile.dev locally with no problems:
docker build -t name/docker-react -f Dockerfile.dev .
=> => naming to docker.io/name/docker-react
docker run -p 3000:3000 name/docker-react
AWS has a hard time with the '.' folder designation and prefers the long form ./
Try to edit the COPY instruction to COPY package*.json ./
And try also to remove the named builder. By default, the stages are not named, and you refer to them by their integer number, starting with 0 for the first FROM instruction.
Your Dockerfile should looks like:
FROM node:alpine
WORKDIR '/app'
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx
EXPOSE 80
COPY --from=0 /app/build /usr/share/nginx/html
You should have a docker-compose.yml, just ensure that you have the right port mapping inside:
Example:
services:
web-service:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "80:3000" # outside:inside container
finally your TravisCI configuration must be edited. secret_acces_key has ONE 'S'
...
access_key_id: $AWS_ACCESS_KEY
secret_acces_key: $AWS_SECRET_KEY
Nginx default port is 80, and AWS only checks docker-compose.yml to manage resources efficiently, just do the right port mapping inside that file
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "80:3000"
volumes:
- /app/node_modules
- .:/app

React + Flask Docker-Compose Containers Unable To Communicate Locally, API Calls Returning net::ERR_EMPTY_RESPONSE In Browser

I have 2 docker containers, the front being a React.js app running on ports 3000:3000 and the back being a Flask API running on 5000:5000.
ISSUE:
I am having an issue with these containers wrapped together in docker-compose where the front will be accessible via localhost:3000 as it would normally run outside a container, however it is unable to communicate with the back container. I receive a net::ERR_EMPTY_RESPONSE in browser when attempting to use any API component. How might I be able to resolve this?
SETUP:
My directory for this docker-compose setup is as follows:
/project root
- docker-compose.yml
/react front
- Dockerfile
/app
/flask back
- Dockerfile
/api
My docker-compose.yml is as follows:
version: "3.8"
services:
flask back:
build: ./flask back
command: python main.py run -h 0.0.0.0
volumes:
- ./flask back/:/usr/src/app/
ports:
- 5000:5000
env_file:
- ./flask back/.env
react front:
build: ./react front
volumes:
- ./react front/app:/usr/src/app
- usr/src/app/node_modules
ports:
- 3000:3000
links:
- flask back
The front Dockerfile:
# pull official base image
FROM node:13.12.0-alpine
# set working directory
WORKDIR /usr/src/app
# add `/react front/node_modules/.bin` to $PATH
ENV PATH /react front/node_modules/.bin:$PATH
# install app dependencies
ADD package.json /usr/src/app/package.json
RUN npm install
RUN npm install react-scripts#3.4.1 -g --silent
# start app
CMD ["npm", "start"]
The back Dockerfile:
FROM python:alpine3.7
WORKDIR /usr/src/app
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
RUN pip install --upgrade pip
COPY ./requirements.txt /usr/src/app/requirements.txt
RUN pip install -r requirements.txt
COPY . /usr/src/app/
TROUBLESHOOTING SO FAR:
So far I have consulted the following threads on SO:
Flask and React Docker containers not communicating via Docker-Compose - where the package.json needed a proxy addition.
ERR_EMPTY_RESPONSE from docker container - where IP addresses needed rewritten to 0.0.0.0 (this appears to be a unique issue to GO as I never used this form of port and IP configuration in my project)
Neither of these very similar issues have resolved my issue. I am also able to ping the back-end container with the front-end and vice versa. Running the React container while running the Flask API outside of its container also works as expected/intended. If there is any other information anyone would like, I would be happy to provide.
Thank you for the time and patience.

Container internal communication [duplicate]

I have the following docker-compose file:
version: "3"
services:
scraper-api:
build: ./ATPScraper
volumes:
- ./ATPScraper:/usr/src/app
ports:
- "5000:80"
test-app:
build: ./test-app
volumes:
- "./test-app:/app"
- "/app/node_modules"
ports:
- "3001:3000"
environment:
- NODE_ENV=development
depends_on:
- scraper-api
Which build the following Dockerfile's:
scraper-api (a python flask application):
FROM python:3.7.3-alpine
WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "./app.py"]
test-app (a test react application for the api):
# base image
FROM node:12.2.0-alpine
# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:/app/src/node_modules/.bin:$PATH
# install and cache app dependencies
COPY package.json /app/package.json
RUN npm install --silent
RUN npm install react-scripts#3.0.1 -g --silent
RUN npm install axios -g
# start app
CMD ["npm", "start"]
Admittedly, I'm a newbie when it comes to Docker networking, but I am trying to get the react app to communicate with the scraper-api. For example, the scraper-api has the following endpoint: /api/top_10. I have tried various permutations of the following url:
http://scraper-api:80/api/test_api. None of them have been working for me.
I've been scavenging the internet and I can't really find a solution.
The React application runs in the end user's browser, which has no idea this "Docker" thing exists at all and doesn't know about any of the Docker Compose networking setup. For browser apps that happen to be hosted out of Docker, they need to be configured to use the host's DNS name or IP address, and the published port of the back-end service.
A common setup (Docker or otherwise) is to put both the browser apps and the back-end application behind a reverse proxy. In that case you can use relative URLs without host names like /api/..., and they will be interpreted as "the same host and port", which bypasses this problem entirely.
As a side note: when no network is specified inside docker-compose.yml, default network will be created for you with the following name [dir location of docker_compose.yml]_default. For example, if docker_compose.yml is in app folder. the network will be named app_default.
Now, inside this network, containers are reachable by their service names. So scraper-api host should resolve to the right container.
It could be that you are using wrong endpoint URL. In the question, you mentioned /api/top_10 as an endpoint, but URL to test was http://scraper-api:80/api/test_api which is inconsistent.
Also, it could be that you confused the order of the ports in docker-compose.yml for scraper-api service:
ports:
- "5000:80"
5000 is being exposed to host where docker is running. 80 is internal app port. Normally, flask apps are listening on 5000, so I thought you might have meant to say:
ports:
- "80:5000"
In which case, between containers you have to use :5000 as destination port in URLs: http://scraper-api:5000 as an example (+ endpoint suffix, of course).
To check connectivity, you might want to bash into client container, and see if things are connecting:
docker-compose exec test-app bash
wget http://scraper-api
wget http://scraper-api:5000
etc.
If you get a response, then you have connectivity, just need to figure out correct endpoint URL.

Skaffold Kubernetes does not display React changes

The issue:
When running skaffold and update watched files, I see the file sync update occur and nodemon restart the server, but refreshing the page doesn't show the change. It's not until after I stop skaffold entirely and restart that I see the change.
Syncing 1 files for test/dev-client:e9c0a112af09abedcb441j4asdfasfd1cf80f2a9bc80342fd4123f01f32e234cfc18
Watching for changes every 1s...
[client-deployment-656asdf881-m643v client] [nodemon] restarting due to changes...
[client-deployment-656asdf881-m643v client] [nodemon] starting `node bin/server.js`
The setup:
I have a simple microservices application. It has a server side (flask/python) and a client side (react) with express handling the dev server. I have nodemon on with the legacy watch flag as true (For Chokidar polling). On development I'm using Kubernetes via Docker for Mac.
Code:
I'm happy to post my code to assist. Just let me know which ones are most needed.
Here's some starters:
Skaffold.yaml:
apiVersion: skaffold/v1beta7
kind: Config
build:
local:
push: false
artifacts:
- image: test/dev-client
docker:
dockerfile: Dockerfile.dev
context: ./client
sync:
'**/*.css': .
'**/*.scss': .
'**/*.js': .
- image: test/dev-server
docker:
dockerfile: Dockerfile.dev
context: ./server
sync:
'**/*.py': .
deploy:
kubectl:
manifests:
- k8s-test/client-ip-service.yaml
- k8s-test/client-deployment.yaml
- k8s-test/ingress-service.yaml
- k8s-test/server-cluster-ip-service.yaml
- k8s-test/server-deployment.yaml
The relevant part from Package.json:
"start": "nodemon -L bin/server.js",
Dockerfile.dev (Client side):
# base image
FROM node:10.8.0-alpine
# setting the working directory
# may have to run this depending on environment
# RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# add '/usr/src/app/node_modules/.bin' to $PATH
ENV PATH /usr/src/app/node_modules/.bin:$PATH
# install and cache app depencies
COPY package.json /usr/src/app/package.json
RUN npm install
# copy over everything else
COPY . .
# start the app.
CMD ["npm", "run", "start"]
It turns out I was using the wrong pattern for my file syncs. **/*.js doesn't sync the directory properly.
After changing
sync:
'**/*.css': .
'**/*.scss': .
'**/*.js': .
to
sync:
'***/*.css': .
'***/*.scss': .
'***/*.js': .
It immediately began working.
Update:
On the latest versions of skaffold, this pattern no longer works as skaffold abandoned flattening by default. You can now use **/* patterns and get the same results.

Resources