-: In the last section
we just about finished up our Docker Compose file,
but you might notice that we made absolutely no mention
of any ports inside this file.
So as it stands, nothing is exposed to the outside world,
and our browser cannot connect
to any of the different servers
that are listed inside of here.
I also want to remind you
that on this development diagram we were looking at
of the overall architecture of our app,
we had showed this Nginx server out
in the very front of everything.
Now, we had made use of Nginx
on the last Docker Compose project we put together
that we deployed eventually off to Elastic Beanstalk.
But the purpose of that Nginx server
on that previous project was to host
all of the different React source code files
or production files, really that we had put together.
So that was a production environment
that was making use of Nginx.
This time around, we're saying our development environment
is going to have Nginx.
So let's talk about why it's here.
Okay, in this diagram,
we've got the browser on the left hand side
and two of the different servers
that exist inside of our development environment.
Next to the browser
is a list of some of the different requests
that the browser is going to make to our environment.
So the browser at some point in time
is gonna ask for an index HTML file.
It needs an HTML file to show on the screen of the browser.
And when it loads up that HTML file,
it's probably gonna need a JavaScript file as well,
like some file that has all the JavaScript code
for the React side of our application.
Now, in addition to that,
we know that the browser
is also going to make some API requests
to the Express server
to get a list of all of the different values
that have ever been submitted,
and a list of all the different current values
that have been calculated by the worker process as well.
So we know that chances are,
the index HTML and the JS requests
need to go over to this React server,
but these API requests
need to go over to the Express server.
So we really want to have something
that kind of enforces routing that looks like this,
but as it stands right now,
we don't really have any infrastructure whatsoever
to kind of take these requests
and send them to the Express server,
or take these requests
and send them over to the React side of things.
So as you might guess,
that is the entire purpose of the Nginx server
that we're going to add in.
The Nginx server is gonna look at
all these different requests
and decide on which backend service of ours
that we want to rend,
excuse me, that we want to route the request to.
Now, before I show you the diagram
to explain how that is done,
I wanna remind you something
that we had written into the source code of both our client
and server projects.
So if you didn't watch the videos
on us putting together all the source code,
you might have not seen this,
so you probably didn't seen it,
but let me just very quickly show you something
on the client and server sides.
In my server directory, I'll find the index.js file.
Inside of here,
you'll notice that all of our route handlers
are like /values/all, or /values/current, or /values.
However, in the client srcbib.js file,
you can scroll down a little bit
and you'll see that we are making network requests
to routes of /API, /API, /values current and /values all.
So the client thinks that
it needs to make requests to /API,
but it's very clear that the server
is not set up to receive that /API route one bit.
No configuration over here to handle that route.
All right, so with that in mind,
let's now take a look at what the Nginx server
is going to do for us.
So we're gonna add in an additional container
to our application
by adding in a service to the Docker Compose file.
That additional service is gonna start up an Nginx server,
and that Nginx server is going to have essentially one job.
Anytime a request comes into Nginx,
it's gonna look at the incoming request.
And more specifically, it's gonna look at the request path.
The incoming request is gonna say,
Okay, does it have /API?
If /API is in the route
that this request is trying to access,
then I'm going to redirect this request
over to the Express server.
Otherwise, if it is not looking for something
that says /API,
I'm gonna direct that request
over to the React server instead.
And Neil, I'm now thinking maybe
a clearer way to organize this diagram
would be to swap those two pieces like so.
Okay, so think about what that's gonna do.
Now, anytime the browser makes a request
that is intended for the API,
here's the inside the srcfit.js file,
it is going to make a request from the browser
to our backend server.
The entire Docker Compose cluster, everything inside there.
And these requests right here
are intended for the Express API.
And so they are adding on /API to the very front.
So now whenever these requests
that have /API on them in reality
come into the Nginx server,
Nginx is gonna say,
Oh, I see that you're looking for the API.
So it's gonna take those requests
and send them on automatically to the Express server.
But in the case of looking for any resources like index html
or main.js right here, it's gonna say,
Oh, I see you are not looking for an API resource.
So rather than trying to send you off to the Express API,
I'm gonna send your request
over to the React server instead.
So that's how routing is gonna work in our application,
and that's how we're gonna make sure
that we can just expose this one service right here,
make requests to it,
and poof, all of our requests are gonna end up
in the correct location.
Now, the last thing you might be a little bit curious about
is why did we not just assign a port
to both the React server and the Express server
and just try to access a port on local host
for like Express server.
Well, let's think about that for a second.
So essentially we're saying, why didn't we say,
Oh yeah, just make the Express server available
on like Port 3000
and the React server available on port, I don't know
4,000 or whatever it might be.
And then whenever our browser makes a request,
it can just specify the appropriate port.
The reason that we didn't do this
is that think about how our application runs
in a production environment.
In a production environment,
we probably don't wanna have to worry
about juggling these different ports.
It'd be a lot nicer if all of our front end React code
could just make requests to some common back end,
and not have to worry about specifying,
Oh, this is a request to my Express server,
so I need to make sure that I'm specifying port 3000.
In other words, it would not be very convenient
every time that we want to make a request over here
to have to append on something like,
yeah, make a request to this route :3000 or :5000
or whatever it's supposed to be.
It's a lot easier to just say,
Oh yeah, this is a request intended for this service.
I'm gonna put on /API.
Now you might be thinking,
Steven, well, what's the difference between
adding on something to the front of the route
and something to the end of the route?
The difference here is that when we are specifying a port,
the port can very easily change.
Depending on the environment that we are deploying to,
one day our API might be hosted on port 5000
inside of all these Docker Compose containers,
and the next day it might be on port 50,001,
you just don't know.
These ports are sometimes very finicky
and sometimes for various reasons,
they need to change all the darn time.
And so it's a lot easier to just specify
this very constant token right here of /API and just say,
Okay, like here /API, this is the destination,
and we can then rely upon Nginx to do the routing for us.
All right, so that's why we are adding on that /API
to the front of all these routes.
We're using that to specify
where the request should be routed off to
inside of all these different services
that we are creating inside of our Docker Compose file.
Now the very last thing I wanna mention here is,
adding on the /API doesn't really solve the issue
of how our Express route handlers.
So if you look at the server directory
and find index.js inside there,
you'll see that all of our request handlers here
are not specifying a /API on the very front of it.
And the reason for that
is that after Nginx does this little routing step,
it's then going to chop off the /API part of the route.
So if something like API values all comes into Nginx,
when it comes out of it,
it's going to be simply /values /all like so.
That's kind of nice
because it means that we can specify these routes
with configuration that only really changes
at the Nginx layer,
and we don't have to like customize
the routes defined in the Express server based upon
whether it's supposed to be watching for /API or not.
Now that is an optional setting, just so you're aware.
If we wanted to, we could absolutely say,
Oh yeah, do not try to chop off the /API,
and we could just change all the routes on the Express side
to watch for /API as well.
But my personal opinion is
it's easier to just chop that off.
And then the Express server doesn't have to always specify
Oh yeah, watch for the route /API
/whatever I actually care about.
All right, so that's probably more
than you ever want to know about routing.
So let's take a quick pause right here.
We're gonna come back the next section
and start putting this Nginx server together,
and make sure that it has some routing
based upon the path name.
So quick break and I'll see you in just a minute.