Before we ensure that data persists
and so on, let's continue with the backend,
let's also dockerize that.
For this I'll go to the terminal
where I have my node server running,
and I will again quit it with control C,
and now I want to put this into a container.
For this, we need to write our own Docker file,
to build our own image for this project.
We didn't need to do this for MongoDB,
because we already have this official image,
which starts database,
but of course,
there's no official image for our own custom application.
Now, here we start with from,
and we use the node as a base image.
We could also add the 14 tag to use version 14
or node like this to use the latest version.
Next, I will set the working directory
to a directory of my choice,
and I will go with app,
which I used a lot throughout this course,
but you can use any other folder here of course.
Thereafter, we wanna copy the package .json file,
into this working directory
and then run the npm install command
to install all required dependencies of this project.
There after we can copy the remaining code
in our host machine project folder
to this working directory in the container,
and then also expose the port used by this application.
And in app.js we can see that is port 80,
so therefore I wanna expose port 80 here.
Now last but not least,
we specify the command that should be executed
when this container starts based on this image,
and there for the moment I wanna execute app.js,
with the node runtime.
Which is available because we're using
the node base image.
Now that's my Docker file for this backend here,
nothing too fancy.
It's basically what we did over and over again
throughout this module,
and it is a quite straightforward Docker file
for a node application.
Now, with that edit, we can now build an image.
And for this, first of all,
I'm going to run Docker image prune -a
to remove all unused images I have on my system
to clean up everything there,
and there after with Docker build dot
we can build this image.
I'll give it a tag of goal,
goals node, that's my image name here.
And this will now build this backend image
based on this Docker file,
and since I cleared all images,
it starts by downloading the node image
and then it will go through these instructions,
creating all those layers,
and it will create my own custom image here,
which we then thereafter can use to spin up our container
for this backend.
So let's wait for this image creation to finish.
Here we go. It is finished.
And now with that finished,
we can run a container based on this newly created image.
So I will add a container or I will run a container,
giving it a name of goals, backend, maybe,
and run a deleting it when it gets stopped
and running it in detached mode.
Actually, initially I'll not run it in detached mode,
I'll just run it like this.
And if I now hit Enter,
we will see that this actually starts up.
And initially it looks like everything works,
but after a couple of seconds, it actually crashes here.
And it crashes because it failed to connect to MongoDB.
And that makes a lot of sense here
because we have MongoDB running in a container
exposing its port,
but in the dockerized backend application,
I am reaching out to local host.
And that now,
since this application is now inside of a container,
means that I'm trying to access
some other service on this port
inside of that same backend container,
not on my host machine.
You'll learn about that in the networking module.
And there you'll also learn how you can solve that.
There is a special alternative domain or address,
which you should use here
and that's host.docker.internal.
That's a special address, a special identifier,
which is translated to your real local host machine IP
by Docker.
So if we do that with this MongoDB container,
still up and running, which it is, if we do that,
we should be able to launch this.
So for this, first of all,
I will rebuild this image since I changed the source code,
so let's do that,
and there after, I will run this container again, like that.
And now this looks better,
now we get disconnected to MongoDB log message,
which proves that indeed, this did connect.
So our backend is now dockerized,
it's in a container and it's able to talk to MongoDB,
but at this point, we'll have a new problem.
The React frontend application
will not be able to talk to this backend.
If I go back to my running React application,
if a reload, I get this error, "something went wrong."
And if I opened the developer tools in the browser,
I see that I got this "connection refused" error.
Indeed, the react application fails to talk to the backend
because whilst the backend is running in a container now,
we're not publishing the ports which it exposes.
And therefore,
the frontend trying to talk to this backend application
on specific ports fails.
Now we do have this expose instruction in the Docker file
of the backend application,
but as you learned, this alone doesn't do much.
Instead, you need to publish the ports
that should be available on your local host machine
when you run a container.
So therefore here in a new terminal,
I'll list the running containers,
and I will stop the goals backend container,
which we just started
so that we can restart it
but this time with the correct ports being published.
So now that it's stopped,
we can again run this goals backend container,
but now I will run it in detached mode by adding -d
and very important with the -p option
to publish the internal port 80,
which is exposed by this container
and which is the port on which the application
is listening inside of the container
to my local host, port 80.
And with this, we start this container again,
and it is now up and running.
And now the React application,
which currently is not dockerized yet,
will be able to talk to this backend.
So if I now reload, this error is gone,
and now we should also be able to add a goal,
and if I reload, it's still there.
So now two of three parts
are dockerized only the frontend is missing.