All right.
This video is going to be really crazy, because we're going to set up an entire e-commerce application
that is composed of many different microservices.
Uh, one of them is a flask microservice, spring boot, um, flask again, Node.js go, so on and so
forth.
All of these different microservices APIs written in different languages, different frameworks are
all going to be managed and orchestrated by one e-commerce UI.
So it follows that we're going to start by containerizing the e-commerce UI.
First.
Uh, if you go inside of Server.js, we have, uh, some instructions from the developer of this app,
myself, in this case, about how this application would typically run in bare metal.
And once we understand how the application runs, we can mimic that workflow using Docker.
So copy everything here inside of the Docker file and comment it out.
Okay, in order to run these JavaScript applications, the react app and the node server, we're going
to, we're going to leverage an environment of node version 14.
That's going to be the base image.
Now we're going to set the working directory inside the container Workdir slash app okay.
Now the working directory is going to be split in two.
Uh, part of it is going to contain the client code.
And the other part will contain the server code.
We'll start with the server code.
So here typically on bare metal you would go to the server directory and run npm install to install
the server dependencies on Docker.
What I'm going to do is copy Over.
Um, so the Docker file is inside of the same directory as the server folder that contains all of the
server files.
So what I can do is copy the contents of the server folder into the working directory slash app slash
server okay.
And now I want to navigate to the working directory slash app server, which means everything from here
on out is going to happen there.
All right.
Inside of the working directory slash app server we've copied over everything here.
Which means we're going to have at this point at line number 14, direct visibility to package.json
and package-lock.json.
So if I say um run npm install here, it's going to be able to successfully install the dependencies
inside the Dot JSON files inside of our slash API slash server working directory.
So at this point we were able to install the server dependencies uh using Docker.
Now we navigate to the client directory and run npm install for the react app dependencies.
So we change back to the app directory Workdir slash app.
And in order to run the application, the next step is to install the dependencies for the react app.
So we're going to copy over all of the code, the contents of client into slash app slash client.
And now if we change to the client directory Workdir slash app slash client, everything from here on
out is going to happen inside of this directory we copied into slash app slash client everything inside
of here.
So at this point line number 26 we should have direct visibility to these package dot JSON.
So if I run npm install at this line over here, it's going to install all of these client dependencies
inside of these package dot JSON.
And all of that is going to happen inside the client directory.
All right.
So now that we've installed the dependencies for the react application, we're ready to build the react
app.
We can do this by saying npm run build.
So after installing the react dependencies we can run npm run build to build the react app.
So all we care about is how the developer was able to run this application, this e-commerce UI locally,
and we're just mimicking that.
And we're just mimicking that workflow using Docker.
So now we run npm run build that's going to build the client code that's inside of this working directory.
After building the client code, uh, we navigate back to the server directory and run node app.js.
Um, this should be node server.js.
But whatever.
Um change back to the app directory.
So now we change back to slash app.
We're actually going to change back to slash app server okay.
Because we need to run Server.js.
At this point we've installed the dependencies for the server.
We've installed the dependencies for the client and built it.
So now all we got to do is run the server and everything should work out smoothly.
So we expose the port that the server is going to be running on.
That's port 4000.
And now we run the Node.js server when the container starts.
So at this point we're inside the working directory slash app server.
Now the last step is to provide the container with a command that it can use to execute the application.
That's going to be node server dot js Server.js should be directly inside of the working directory slash
app server.
So this command should work out beautifully.
It's pretty amazing how we were able to take the instructions of how this application would normally
run in bare metal, and mimic that workflow using Docker.
All right.
Let's go ahead and build this image.
Docker build t um do do do do.
Oh make sure that your CD into e-commerce UI before you do this docker build t ecommerce UI followed
by a dot to build a docker file.
To build an image from the docker file at the current directory.
All right, I do have a lot of dependencies in my react app.
Um, so this should take quite a while.
That's okay.
We're patient people.
It is what it is.
All right.
That took a really long time, but whatever.
Now let's go ahead and create a container from this image.
Uh, the container is going to map port 4000, where the Node.js server is going to run to a host machine
port 4000.
It is going to be called node.
No, it's going to be called e-commerce UI.
Um, I don't think I'm missing anything.
Let's just create a container out of the image.
We have the port image.
Let's do it.
I forgot the dash dash rm.
But it's okay.
I don't think it will get removed automatically anyway because there are some interlinking stuff.
Um.
All right.
Beautiful.
Now you can see here I'm already logged in because I was playing with the app earlier and it persists
the state.
But anyways, you should be logged out if you're not logged out.
If I try to create an account, it should fail.
I'm going to say something like Bill, Bob, address 123.
Private road.
Postal code.
Some postal.
Code.
Some email.
Bob at gmail.com.
Password.
Let's say love.
Um, I'm just gonna screenshot this for later in case I forget it if I try to sign up.
It's obviously not going to work, right.
Because the only thing we have running is the e-commerce UI.
Um, in order for us to be able to sign up or sign in, we need to also run the authentication microservice,
the profile management microservice, and connect our e-commerce UI to it.
All right.
So we can start by creating a network.
Uh, both containers need to be running on the same network for them to be able to talk to each other.
So we're going to create a network called Docker.
Network.
Create my network.
All right.
I'm going to stop the e-commerce UI from running.
And I'm going to Docker rm E-commerce ui f.
Okay.
Uh, now I'm going to CD into workbook starter projects, oh three starter projects, and I'll CD into
profile management.
We need to run our profile management inside of the same network as the e-commerce UI, in order for
the e-commerce UI to be able to authenticate our dear friend Bob.
All right.
I didn't leave any instructions for this file because all it is is a Node.js application that can be
run using node auth API.
JS.
This one doesn't have a react front end that it needs to render to the browser.
So.
Uh containerizing.
This one is going to be really easy.
All we got to do is install the dependencies inside of package.json and then run the app.
Very similar to how we were containerizing the flask applications.
So from node 14 that's going to be the base image.
We can use the pre-configured environment node 14 to run our node app the working directory slash app.
Notice how repetitive this becomes.
Um repetition is good.
It means you're getting the hang of things.
Then we're going to copy both package.json.
I can do this by saying package star.
So star should include anything between package and the dot JSON.
So that's going to copy over both files into the working directory.
Okay.
Um then I'm going to install the dependencies inside of the package dot JSON that I copied into the
working directory.
So run npm install that's going to install all the dependencies.
Then I can copy the rest of the application source code.
So copy the rest of the source code.
I can just copy everything from the current directory into the containers is working directory.
I have.
I already have a docker ignore that ignores the docker file in the readme.
So we can do that without having to worry about the wrong thing going in there.
Explore.
Expose the port that the API listens on.
Um, the API listens on.
Port is going to be listening on the container port 3003.
So we tell whoever is creating a container from this image that that's the port they need to map to
a host machine port.
Run the Node.js application when the container starts.
So here we provide um, the container, not maven, the container with the command that it can use to
run the app.
So it's going to be node um auth API dot js.
All right.
Very simple.
Docker build dash t profile management.
Build an image.
How easy was that?
Now we say docker run.
Um, did I already create a network?
Docker network ls.
So we have a network called my network.
We're going to run, um, every service on my network so that they can talk to each other.
So Docker run network is going to be set equal to my network.
All right.
We're going to call this dash dash name.
Uh profile management.
It's really important that you keep track of what the container name is, because that's going to be
the host that the e-commerce UI will use to connect to this app.
Uh dash port 3303 will map the container port 3303 to the host machine port 333003.
Um, you don't actually need to map the container port to a host machine port, because the e-commerce
UI is going to be connecting to this profile management microservice directly.
But if you want to access this microservice through the browser and test some of its endpoints, you
can feel free.
So I'm just going to map the container port anyway.
And we're going to create a container from the image profile management.
All right.
Am I missing anything.
No I'm not.
Okay.
Now let's go to the e-commerce UI.
The e-commerce UI has a list of environment variables.
Okay.
Each environment variable by default is going to be set equal to local host.
Unless we set those variables in the environment that the app is running in inside of the container.
So what we need to do is set the profile API host equal to HTTP slash the container name.
We need to use the container name as the host, so that our e-commerce UI is able to find the application
that's running inside of that container within the same network.
So if you're curious about where this environment or environment variable is being used, go to the
server, go to the routes uh auth dot js.
It's being used right here.
So if we set the environment variable properly this should translate to HTTP slash the container name
profile management.
That's going to allow it to find the application that's running inside of this container within the
same network.
My network uh, followed by the container port 3003 followed by whatever paths are provided by the API
by the microservice itself.
Anyways, enough talking.
Let's just give the application the environment variable that it needs to connect to the microservice
that's running on the same network.
So dash e, the environment variable is the following.
We need to set that equal to http slash slash.
Um, the container name running on the same network as profile management.
All right.
Fingers crossed.
So remember before authentication didn't work.
Let's try it again.
Create an account.
Bob.
Bill.
Um.
Bob.
Crescent.
Um B1BB2B email Bob at gmail.com.
Password.
Let's say love.
Request two.
Profile management 3003.
So what happened there?
The fetch request failed because I'm not running it inside of the same network.
Sorry, guys.
So Docker rm uh, e-commerce UI dash f and then after.
Um, before setting the port, I'm going to say dash dash network my network.
Let's try that again.
All right.
Create an account.
Bob.
Bill, address B-1b, B2B postal code.
Um.
Oh, that's not an address, but whatever.
The information doesn't have to be accurate.
Bob at gmail.com.
Love.
Sign up.
Beautiful.
Go away.
So sign up.
Worked.
Now we can sign in using Bob's credentials.
Bob at gmail.com.
Love sign in.
Great.
Everything worked beautifully.
So here we're signed in as Bob.
Bill.
Notice that Bob, by virtue of connecting to the profile microservice, we also have access to profile
management because all the profile management is happening inside of this service, which means the
e-commerce UI is able to successfully connect to it whenever it needs to.
Now the address doesn't make any sense, so I can change it to one, two, three private road or something
and maybe make this Bob slim.
All right.
Beautiful.
So everything worked beautifully.
If I refresh, notice that this is now BS for Bob slim, not for you know what?
All right, so now we still need to connect to the product catalog inventory.
Contact us.
Shipping.
Let's dockerize all of these microservices and connect our e-commerce UI to it.
So let's create another terminal.
And the next one we're going to do is shipping and handling.
So this application is written in go.
And in order to run this application all you need to do is say go run Main.go pretty simple.
That's why I didn't really leave instructions.
But instead of running this bare metal, we're going to run it inside of a Docker container because
I don't feel like installing go into my machine first and foremost.
We'll already have go on my machine, but I don't want you to install it.
Um, all right, let's go ahead and set up a base image of Golang 1.20.
That's the image that's going to be used to run everything.
Working directory is going to be slash app.
We're going to copy.
So the Docker file is inside of the same directory as the main.go file.
So we can just say copy main.go into the working directory.
Expose the port that the API listens on.
That's excuse me, port 8080.
This must be the longest video I've ever made because I am getting really thirsty.
Run the code when the container starts.
Uh.
Go!
Run!
What am I doing?
Go run!
Main.go.
All right.
Pretty simple.
So all I needed to know was this information and I was able to make an image.
Isn't that beautiful?
Docker build t o sees.
I need to go to CD workbook.
Starter Projects oh three Starter Projects shipping and handling and Docker build dash t shipping and
handling.
Um, what am I trying to autocomplete a name?
Docker build t shipping and handling.
Build an image out of the docker file in the current directory.
Hope I didn't make any mistakes.
Now we're good.
Docker run.
We need to run it in the same network as every other service, which is my network dash P will.
We don't really need to map the container port to a host machine port, because I'm not going to access
this from my browser.
Uh, the e-commerce UI is going to connect directly to it, but whatever docker run dash, that's it.
We just create a container from this image, and I need to name the container so that I'm able to access
it using its name later on.
Shipping and handling.
All right.
So now that's running on port 8080, which means in the e-commerce UI I can stop this control Z.
I can stop this and remove the container.
So docker rm e-commerce ui dash f rerun the container.
Adding another environment variable.
So the e-commerce UI relies on another environment variable.
Uh react app shipping API host that it uses in its code to connect to a shipping API.
The default is localhost unless we override this within our container environment.
So dash e shipping API host and we give the application the information that it needs to connect to
the microservice.
So http uh the container name was shipping and handling.
So the application itself has no idea where the, uh, shipping API is going to be.
It relies on us to give it a host so that it can find where it's running.
In this case, we tell it that it's running inside of the shipping and handling container, which happens
to be inside of the same network oopses.
Let me remove that.
All right.
Localhost 4000 Shipping beautiful.
It's able to connect to the shipping and handling API showing us this beautiful table.
The next thing I want to connect to is the Contact Us API.
So this one is a very, very simple flask app.
I bet at this point that you can do this with your eyes closed.
If not, no worries, we'll go through it now.
So let's use Python 3.8 slim.
All right.
Now we're going to set the working directory to be slash app.
Then we're going to copy um so the Docker file is inside the same directory as the requirements.txt.
So we can just say copy requirements.txt into the working directory.
We can install the dependencies.
Um you don't have to know the command.
You can ask whoever developed this app, but I know it to be dash r requirements.txt.
After installing the dependencies, we can copy, uh, we only need to copy server.py into the working
directory, the app.
The container port that it's going to use is port 8000.
So expose port 8000.
Run the flask app when the container starts.
Remember there are two ways to run flask applications.
The annoying way which is to use flask run to set a shell environment variable, and the simple way
which is just to say Python server.py.
You know me, I like to keep things simple.
So let's do that.
Uh, create another terminal for the contact support API.
So we'll go CD workbook starter projects oh three starter projects.
Um, contact support team all right.
Docker build t contact support team.
Build an image from the Docker file.
All right.
And then we're going to say docker run.
Keep the image name there for reference.
Docker run dash dash network my network.
We don't have to map it to a host machine port, but we will anyways.
Um, is that it?
No, we need to name the container.
That's really important so that we're able to identify the host from our e-commerce UI app.
Beautiful.
Next, you know what?
Just for you, I'm going to access it from my browser just to show you an example.
So if we go to localhost 8000 slash this endpoint, it shows us the message that it would send to the
e-commerce UI when the e-commerce UI asks for it.
Anyways, uh, let's copy over the container name.
Stop this thing, remove the container.
Rerun it using the environment by passing into it.
An environment variable.
Uh, sorry, my brain froze for a sec.
Environment variable.
Contact API host.
HTTP.
The container name is contact support team.
All right.
So in the interests of transparency.
So that's going to be HTTP contact support team 8000.
Whatever.
So um this tells our e-commerce UI to connect to the application that's running inside of the contact
support team container.
All right.
Which happens to be running on the same network as the container that's running this app.
So that should work out beautifully.
Server is running on port 4000.
Let's test it out.
So now it should connect to contact us.
Let me refresh.
Nice.
If I put a subject uh, worried about purchase.
Uh, I bought the wrong product.
Submit.
Everything works beautifully.
So contact us.
Is working.
Profile management is working.
Shipping I think is what we made work before.
All right.
There's still three more things we got to do.
Product catalog, inventory and order management.
We'll do inventory.
Um.
By the way, um, this one is a Python application, so you can feel free to pause and try this Docker
file out yourself.
It's going to be very similar to this one.
I'm just going to go ahead and copy it because I'm getting a bit tired and lazy.
Uh so we'll go to product inventory.
Uh the base image won't change.
Work directory won't change.
There's a requirements.txt file.
Uh, dependencies.
What's the Python app called?
Inventory API dot p y.
The port is 3002, by the way.
Repetition is good.
It means we're getting the hang of things.
Python inventory api.py.
All right, so now, um, let's make sure we didn't miss anything.
Create another terminal.
We'll CD into workbook starter projects zero three starter projects product inventory.
Okay so we're at the product inventory.
Uh, we're going to go ahead and build an image from this Docker file.
Docker build dash t calling this product inventory.
Create an image from the docker file at the current directory.
All right then I'm going to say docker run dash dash network my network.
Um we don't need to map the container port but we will anyways
Okay.
Um, the image name is Product inventory.
I'm going to set that as the container name as well.
Dash dash name.
Product inventory.
We'll create a container from the following image.
Run that.
All right.
And now from the e-commerce UI we set another environment variable.
So first delete the stopped container.
Set another environment variable dash e and the environment variable that the application expects and
embeds into its API routes.
Be this environment variable that we set.
Is equal to product inventory HTTP colon slash slash.
We want this to map to product inventory.
3002 the inventory management option relies on us setting up the inventory API, as well as the product
API, which currently has an undefined environment variable.
We haven't set up the product API yet, so we should have set up the product catalog first, which we'll
do right now.
So we'll CD into um, workbook starter projects.
Oh three starter projects.
We'll CD into the product catalog.
All right.
What is this.
It is a node JS app.
And running it is going to be very similar to something we've done before right over.
What was it.
Profile management.
Yep.
We can literally just copy this over into product catalog.
All right.
From node 14.
Da da da da da da.
Uh, the port that this one uses, the container port is going to be port 3001.
Okay.
Uh, port 3001.
Now, here we run node index.js.
All right.
Simple.
So we clear the output.
Uh, docker build t, um, product catalog.
Then I'm going to create a container docker run.
I'm going to create a container named.
Um, actually before we start with the name Create a container at the network.
My network?
Um, whose port 3001 container port is mapped to a host machine port 3001.
Again, the e-commerce UI is going to be connecting to the product catalog directly within the same
network.
So we don't need to map this to the host machine.
Uh, it's only for us if we decide to access this API's endpoints through the browser.
Um, and that's pretty much it.
Oh no.
We still need to name our container.
And okay.
And we're creating a container from the image that we just built.
All right.
And now I can stop this process and remove the e-commerce UI app container and create another container.
With another environment variable this time.
To do to do so many folders.
Uh.
Product API host set that equal to HTTP slash product catalog I believe is what we called the container.
So you get the point by now.
Go to inventory management.
Now it works because this page relied on two APIs in order to run properly.
And if we go to product catalog this one works as well.
The final service we need to configure is the order management.
Because if I try to add to cart, I'm going to get an error.
If I try to go to order management, I'm going to get an error as well.
So let's fix that and we should be done.
All right.
Isn't that crazy how much progress we've made in one video?
You're you're running an e-commerce application, uh, having just learned Docker.
So I hope you're proud of yourself.
If you're if you've been able to keep up so far.
Let's continue.
Uh, we're going to CD into, uh, order management.
So CD workbook Starter projects, CD oh three Starter Projects order management.
And let us create the Docker file for this Spring Boot app.
So we've already created one, uh, in the previous lesson before.
So what I'm going to do, remember we need to use a maven as well as a Java runtime.
I'm going to use Maven 3.6.3 open JDK 17 slim.
This was actually the the version of Maven and Java that I used when building the Spring Boot app.
I'm going to set the working directory inside the container Workdir slash app.
I'm just going to copy everything over.
Then I'm going to run Maven install.
That is going to be used to install all the dependencies inside of Pom.xml.
All right.
Uh, expose the port that the application listens on.
Uh, the application I'm sure listens on port 9000 or something.
Port 9090.
Okay, I'm going to.
So expose port 9090.
Define the command to run when the container starts.
So after running Maven install, we can simply Say Maven spring boot run.
All right.
Docker build.
So this is nothing new.
We did this in the lessons.
I'm not going to bother re-explaining the maven build process.
Docker build t we're going to call this order and management.
We're going to create an image from the Docker file in the current directory.
All right installing all the dependencies from the pom.xml file.
So in node that's a package.json file in uh in Python that's the requirements.txt file.
You'll get the hang of it.
Um anywho.
So now we simply create a container docker run dash dash network.
My network needs to run in the same network as all the other containers.
And now this Microservice relies on three other microservices.
It relies on the product inventory API host on the Product Inventory API, the Product Catalog API,
and the Shipping and Handling API.
These are the default values that are given to these variables, which will be overridden if we provide
these variables from the environment that the app will be running in from the container itself.
So now, um, before starting up the container, let's just name it.
I'll name it Order Management, the same name as the image.
Why we before specifying the image from which we will create this container, let's specify a port mapping
9090, 90, 90.
We don't actually need to map the container port to a host machine port once again, because the e-commerce
UI is going to connect to this application directly via the Docker network, not through our host network
anyways.
And before we finalize this command, we provide it with the environment variables that it needs in
order to function properly.
So we set the product inventory api API host environment variable equal to HTTP, followed by the container
name where the product inventory API is running, which happens to be inside of the same Docker network.
Then we give this information another.
We give this application another environment variable called product catalog API host, which we set
equal to the container that's running the product catalog HTTP product catalog.
Once again we say dash e shipping handling API host.
Setting this variable equal to HTTP slash slash.
Um, the container where the shipping and handling API is running.
Make sure I got everything.
Shipping.
Handling API host.
Product catalog API host.
Inventory API host.
All right.
Now we simply specify the image from which this container will be created.
And I'm pretty sure we're done.
Sweet.
We run this app.
Um, need to remove the e-commerce UI container dash e.
So the final microservice that we need to manage from our e-commerce UI is the order API.
So this is the environment variable that the e-commerce UI application expects.
We set that equal to HTTP slash the container that's running the app.
And that's it.
Now it has the information it needs to connect to every single microservice, thereby finalizing every
moving part for our app.
So if I go back here and add the Bluetooth headphones product, add it to the cart, and actually,
um, made this application so that if you add it again, already exists, it's a pretty complete e-commerce
app.
The only thing is that I didn't actually add a payment system or whatever, and obviously some corners
were cut because it's just a tutorial app.
But anyways, this is a pretty significant application to containerize and run all at once.
I hope you're proud of yourself.
If you were able to follow along, you should now have the skills to containerize pretty much any app
that you want.
All right.
This is very similar to what you can experience in the real world.
We've got authentication.
We've got order management.
We have over seven different terminal sessions running these microservices, all of them forming a big
e-commerce app.
Now on that same note, we do have six different terminal sessions.
Things are getting very tedious, which is why in the next section we're going to introduce uh, Docker
Compose which is going to streamline our container creation workflow.
I'm excited to see you then.
I hope you enjoyed this lesson.
And on to the next