So if we consider this error
that was thrown, what exactly could be the problem
with this newly added bind mount here?
Well, keep in mind that we're binding this folder,
everything in that folder to the app folder.
Now isn't the end kind of means, of course,
that we overwrite the app folder inside
of the container with our local folder, right.
Now we copy everything into that folder, initially here when
the image is created, and we install all dependencies,
but in the end we render all these steps,
which we performed during image creation worthless,
if we then blind this mount to the container,
because we overwrite everything in the app folder anyways
with our local folder.
And this local folder doesn't have
the node modules folder
with all the dependencies this app needs,
and that's the reason for this error we're getting.
The server JS file needs the express package,
the express dependency, and it exists in a container,
because of npm install, it does not exist in my local setup,
because I never ran npm install there.
And since I mount my local folder
to the app folder, we overwrite all
the work we did here when we set up
the image and therefore also the container.
We overwrite this with our local folder,
and that is the problem here.
Now how can we solve this?
Let's first of all understand how containers interact
with volumes and bind mounts.
If we have a container,
and we don't have a volume, and a bind mount,
we can mount both into the container
with the -V flag,
which I showed you a couple of minutes ago.
That means that some folders inside of the container
are mounted, or are connected
to folders on the host machine.
Now let's say we already had files inside of the container.
In that case, they also now exist in the outside volume,
and if you write a new file, it's also added
in the folder on the host machine.
If the container then stands up,
and it finds files in the volume,
and it doesn't have any internal files yet,
it loads the files from the volume.
That's actually what we utilize with the bind mount.
Here we don't have any files inside
of the container, let's say,
but we have files on the local host machine.
In that case, these files
are basically also usable inside of the container,
but now we have kind of both things happening.
We have files inside of the container in the app folder,
because of these instructions,
and we have files and folders outside of the container
in this folder on our local host machine.
And now the good thing is
that Docker does not start overwriting our local files
on our host machine.
This would be pretty bad,
if Docker would be doing that, right.
We could delete a lot of important things
on our computer by accident.
So that's not what's happening.
Docker will not overwrite our local host folder here.
Instead, here, the local host folder,
and the content in it overwrites what's
in the Docker container,
and that's the problem here,
with that we got rid of node modules and so on.
Now to solve this problem, we kind of need to tell Docker,
that there are certain parts
in its internal file system, which should not be overwritten
from outside in case we have such a clash
as we have it here.
And the debt can be achieved with another volume,
which we add to this Docker container
with an anonymous volume actually.
And this will now also show us a use case,
where anonymous volumes can be helpful.
If we add one more volume with -V,
we can find the app/node modules folder.
And it's an anonymous volume,
which we also can add like this,
and not just in the Docker file.
It's an anonymous volume because it has no name,
it would have a name if we add a colon in front of it,
and assign some name here,
but if we don't do that, it's an anonymous volume.
So this is an anonymous volume,
and adding it like this
is equivalent to adding it like this here.
You could do both, but I'll comment this out
with a hash in front of it and go with this approach,
because I then don't have to rebuild the image.
Now why does this help here?
Well, Docker always evaluates all volumes you
are setting on a container,
and if there are clashes, the longer internal path wins.
So for example here we have a clash,
we have app volume which is bound to something,
and we have an app/node modules volume,
which is also bound to something.
We didn't assign a name,
but keep in mind, even for anonymous volumes,
they are managed by Docker,
and there is some mapped folder somewhere
on the local machine.
It's just cleared when a container is removed,
but there is a folder on the host machine,
even for anonymous modules.
So here, Docker sees that we have some volume mapped
to the app folder,
and some volume to the app/node modules folder.
And in that case, the simple rule Docker has
is that the longer the more specific path wins.
So that means we can still bind to the app folder,
but the node modules folder inside of the app folder,
and the node modules folder is the folder created
by the npm install command by the way.
The node modules folder will survive,
it will overwrite the folder that's coming in
from outside because of this module,
and here, we actually pass in no node modules folder,
and therefore this node modules folder overwrites
the non existent node modules folder,
and hence long story short,
the node modules folder, which was created during
the image creation with npm install will survive,
and will actually co exist together
with the bind mount, which still also works.
It's just a node modules folder,
which is kind of excluded you could say.
And therefore now after this long explanation,
if we stop the currently running container,
and we remove this container,
we can run this container now
with this extra anonymous volume added.
If we want to also again with --RM added,
and now this starts,
and now this app also works again, test this works.
Again, we'll see under feedback, awesome.txt,
that file from earlier is also still there,
but now we actually have one additional benefit.
Now if we change something in our HTML file,
for example, I removed that please text again,
and I save that file, if I now reload we see
that change instantly without rebuilding
the image in between,
and the reason for that
is that now we added this bind mount,
which in this case also only works,
if we add this anonymous module to make sure
that node modules folder doesn't get overwritten
by our bind mount folder content.