So how can we now add such a volume
to our container?
One of the easiest ways of adding a volume
is that we add a special instruction
to the Docker file that creates the image
which we'll later use to create a container.
There we can add the volume instruction.
And this takes an array full of texts,
full of strings and quotes,
where we can specify the different paths
inside of the container file system.
So, which are going to get used
inside of our application code, which we wanna persist.
So in our example, for example
I am saving my permanent files to the feedback folder.
I'm also saving files to the temp folder
but as the name implies, this folder is only temporary.
It does not need to be saved.
But everything in the feedback folder should be saved.
So in my application code,
I'm writing to the feedback folder
which of course in the end is inside of the app folder
since that's our general working directory
where we copied the entire application into.
And therefore the volume
which I wanna save is /app/feedback.
That is the path inside of my container
and that's important, inside of my container,
which should be mapped to some folder
outside of the container
and where data should therefore survive.
Now you might be wondering
how can we control to which folder
on our hosting machine does this map?
I will come back to this later.
At the moment we don't control this.
We let docker control this
and I'll come back to why this makes sense.
So if I saved this ,
this Docker file with this instruction added
we can rebuild this image with docker build.
Now that we added this volume instruction, docker build.
and of course, maybe give it again, a tag
and I will name this feedback-node
and give it a tag of volumes.
We already have feedback-node latest.
Now I give it a special volumes edition, you could say,
which is the same image as before,
but with this extra volume feature.
Hit enter and now this image is created and tagged.
And now we can run a container based on this image.
So docker run feedback-node:volumes
So using that tag, which I just assigned
and I'll run it in detached mode,
I'll publish the internal port 80
to my host port 3000.
And we can also add the --rm flect to remove that container
if we stop it, because thanks to volumes,
this should now not be a problem anymore.
We can also sign a name and I'll name it, feedback-app.
If I enter, I get an error because I already have this app.
I already have this container.
It's actually even a running container.
So I will stop this running container here.
And then also remove it thereafter
since that was not a container created with --rm.
So I'll run docker rm feedback-app.
And now with that removed
now we can restart this container based on this new image.
If I now hit enter, this is up and running.
Therefore, of course, we can go back to local host 3000
add this feedback one more time, save this
and now we have a problem.
Now this starts spinning and it crashes.
So clearly something went wrong.
And in order to see what went wrong,
I'll run docker logs feedback-app
to look into the output of this container.
And we see that we got an error here,
unhandled rejection warning.
And the problem here seems to be
that cross-device link is not permitted.
So when we try to move the awesome.txt file
from the temp folder to the feedback folder that crashes.
And that must have something to do
with our recently added volume
because it worked before.
Now this error, which we're facing
is stemming from this specific code from the rename method
which I'm using here in node to be precise.
Now this is no node course
so I won't bore you with the details.
But in the end, the rename method doesn't work
if the file gets moved across multiple devices.
And thanks to the volume which we specified here
this is kind of what's happening under the hood.
Docker indeed will not just move the file
to some other folder inside of the container file system
but it moves it kind of out of the container.
And it's this specific rename method
which doesn't like things like this.
Now the work around is simple.
You can replace the rename method with the copyFile method
and there after simply add a new line
where you call fs.unlink and point at the tempFilePath
and add await in front of that.
That's all.
This essentially will copy the file
and manually delete it thereafter.
If you change this, you should be good.
Now of course, we need to rebuild our image
because we changed the source code
and that's still not being picked up automatically
at this point.
So to do that, I'll first of all remove the image
with the docker rmi command
and then there it's the feedback-node:volumes tag
which I wanna remove like this.
And then we just need to rerun this docker build command
to rebuild the image.
I'll use the same tag as before, since I just removed it.
And once this was rebuilt, we can run this container again
still using this image which we just rebuilt
and removing the container if it shuts down.
And if you now back to local hosts 3000/
and you try this again, now this works.
And now if you access feedback/
whatever title you picked .txt, you see your file here.
And now hopefully the file is still there
if we stop and remove this container and restart it.
So let's go back and let's stop this feedback app container.
And once it is stopped, let's rerun it
by running the docker run command again.
And this will of course create a brand new container based
on the same image as before.
And if we do that, then go back and reload
well, no, this file is still not there.
So what's up with this volumes thing.
Why am I teaching you about volumes
if we just add an instruction that doesn't do anything
except for break our code?
What's the idea behind that?
Why is it not working?