score:17
If you want to start all of your apps with a single command using docker, the only option is docker-compose.
Using docker-compose is just for test purposes or a very limited production infrastructure. Best approach is to have your artifacts in different host each one.
Please read these to understand some points:
When you use docker-compose, all the services are deployed in the same machine, but each one in a container. And just one process is running inside a container.
So if you enter into a container (for example a web in nodejs) and list the process, you will see something like this:
nodejs .... 3001
And into another container like a database postgres:
postgres .... 5432
So, if the nodejs web needs to connect to the database, from inside, must need the ip instead localhost of postgress database because inside of nodejs container, just one process is running in the localhost:
localhost 3001
So, use localhost:5432
won't work inside of nodejs container. Solution is to use the ip of postgres instead localhost : 10.10.100.101:5432
Solutions
When we have several containers (docker-compose) with dependencies between them, docker proposes us :
As a summary, with these features, docker create a kind of "special network" in which all your container leave in peace without complications of ips!
Docker networks with host.docker.internal
Just for test, quickly deploy or in a very limited production environment you could use a new feature in latest version of docker-compose(1.29.2) and docker.
Add this at the end of your docker-compose
networks:
mynetwork:
driver: bridge
this to all of your containers
networks:
- mynetwork
And if some container needs the host ip, use host.docker.internal instead of the ip
environment:
- DATABASE_HOST=host.docker.internal
- API_BASE_URL=host.docker.internal:8020/api
Finally in the containers that use host.docker.internal add this:
extra_hosts:
- "host.docker.internal:host-gateway"
Note: This was tested on ubuntu, not on mac or windows, because no bodies deploy its real applications on that operative systems
Environment variables approach
In my opinion, Docker links or networks are a kind of illusion or deceit because this only works in one machine (develop or staging), hiding dependencies from us and other complex topics, which are required when your apps leave your laptop and go to your real servers ready to be used by your users.
Anyway if you you will use docker-compose for developer or real purposes, these steps will help you to manage the ips between your containers:
- get the local ip of your machine and store in a var like $MACHINE_HOST in a script like : startup.sh
- remove links or networks from docker-compose.json
- use $MACHINE_HOST to refer another container in your container.
Example:
db:
image: mysql:5.7.22
container_name: db_ecommerce
ports:
- "5003:3306"
environment:
MYSQL_DATABASE: lumen
MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
api-php:
container_name: api_ecommerce
ports:
- "8020:80"
- "445:443"
environment:
- DATABASE_HOST=$MACHINE_HOST
- DATABASE_USER=$DATABASE_USER
- DATABASE_PASSWORD=$DATABASE_PASSWORD
- ETC=$ETC
web-react:
container_name: react_ecommerce
ports:
- 3001:3000
environment:
- API_BASE_URL=$MACHINE_HOST:8020/api
- Finally just run your startup.sh which has the variables and the classic
docker-compose up -d
Also in your react app read the url of your api using a var instead proxy in package.json:
process.env.REACT_APP_API_BASE_URL
Check this to learn how read environment variables from react app.
Here you can find a more detailed steps of how use MACHINE_HOST variable and its use:
Advices
- Use variables instead hardcoded values in your docker-compose.json file
- Separate your environments : development, testing and production
- Build is just in development stage. In other words, don't use build in your docker-compose.json. Maybe for local development could be an alternative
- For testing and production stages, just run your containers, built and uploaded in development stage (docker registry)
- If you use proxy or environment variable to read the url of your api in your react app, your build just will work in one machine. If you need to move it between several environment like: testing, staging, uat, etc you must perform a new build because proxy or environment var in react is hardcoded inside of your bundle.js.
- This is not a problem just for react, also exist in angular, vue, etc : Check Limitation 1: Every environment requires a separate build section in this page
- You can evaluate https://github.com/utec/geofrontend-server to fix the previous explained problem (and others like authentication) if apply for you.
- If your plan is to show your web to real users, web and api must have a different domains and of course with https. Example
- ecomerce.zenit.com for your react app
- api.zenit.com or ecomerce-api.zenit.com for your php api
- Finally if you want to avoid this headache of infrastructure complications and you don't have a team of devops and syadmins,you can use heroku, digital ocean, openshift or another platforms like them. Almost all of them are docker compatible. So you just need to perform a git push of each repo with its Dockerfile inside. That platform will interpret your Dockerfile, deploy and assign you a ready to use http domain for testing or a cool domain for production (prior acquisition of the domain and certificate).
Source: stackoverflow.com
Related Query
- How to connect API with Web SPA through docker
- How do I connect web API to a react project through AJAX?
- How to integrate Web MIDI API with React frontend and Django backend
- Where to save uploaded images in "asp.net core web api with react" spa template and serve images to client?
- How to post a file to a web api from reactjs With react-adal, not Axios
- How to go through multidimensionnal array from API with Reactjs
- How to connect a 3rd party API to React through Express
- How to fetch data through api in redux?
- How use react-redux connect with mapStateToProps,MapDispatchToProps and redux-router
- How to test API request failures with Redux Saga?
- How to use context api with react router v4?
- How to make react router work with static assets, html5 mode, history API and nested routes?
- How to connect state to props with mobx.js @observer when use ES6 class?
- How should the new context api work with React Native navigator?
- How to integrate azure ad into a react web app that consumes a REST API in azure too
- How to pass multiple states through react context api
- How can I serve robots.txt on an SPA using React with Firebase hosting?
- How do you update Formik initial values with the react context api values after an AJAX request?
- How to mock API calls made within a React component being tested with Jest
- How to test snapshots with Jest and new React lazy 16.6 API
- How to secure my react app api with csurf?
- How to implement Google API with React, Redux and Webpack
- How to download a file through an API in React?
- How to connect simple Formik form with Redux store and dispatch an action?
- File upload with ASP.Net Core 2.0 Web API and React.js
- React Select - How to show / iterate through data from api call in option instead of hardcoding options?
- Typescript with Redux, how to use connect without re-declaring action definition?
- How to get the DOM node from a Class Component ref with the React.createRef() API
- How do you test a reactjs web app with selenium?
- How to connect to Laravel Websocket with React?
More Query from same tag
- Update array with elements from another array react
- facing isssue while deleting a target comment
- React/Chartjs change data with a button
- how to get value of checkbox in react js
- send data through onclick event from child to parent React js?
- Call react component from javascript
- Why is my JSX rendering a <tr> when it shouldn't?
- where call setInterval in react
- How to pass data from one component to another in React or React-Redux?
- Specify type for file upload event in react typescript
- Next.js SSR vs. SSG
- React + MobX - not re-rendering update to state
- React Router 4 and props.history.push
- Is there anyway to pass state to getServerSideProps
- Import image from folder in React
- what should a React checkbox alike component expose as API?
- React : Component does use old state when re-render why?
- Passing a data attribute through a stateless component to its HTML output
- How to import my own icons to my function iconNameFromType?
- Connecting frontend and backend MERN stack
- React hooks stale state
- How to set the state inside map function in React?
- React: Default Initial State with Prop Value
- How to remove "[" and "]" signs from array in Javascript
- Attempted to add an ID already in GraphQLSegment
- Anonymous class in React
- how to mock a named import in jest?
- React - in which component should I do http requests?
- How does one deploy a ReactJs component that imports its own stylesheets?
- integrate react semantic ui checkbox with redux form