Complete Intro to Containers (feat. Docker) Volumes
Transcript from the "Volumes" Lesson
>> So I showed you how to do bind mounts, and now we're going to get into volumes. Okay, so this is the other way to mount in new files into this that can survive between runs of containers. The difference between bind mounts and volumes is that bind mounts are literally just files on your computer that you're exposing inside of the container, right?
[00:00:20] Just like what we showed you here, the volume is something that Docker manages for you, it's not exposed on the host, right? Docker is just like, okay, you've created this new volume, this new file system, and I'll just keep it, right? And anytime that you ask for it, I'll hand it back to you, right?
[00:00:35] So this is really useful for things like database, right? So you can have Mongo write to this volume, right? And then any time that the Mongo container goes away and comes back, it'll just start reading and writing to the same volume. So you're basically telling Docker, hold onto these files.
[00:00:48] And the name of these files is Mongo mount or something like that. Does that make sense? So let's go ahead and, we'll make a new directory here. And we'll start a new project. So I'm out of this, and we'll call this one volumes. Cd into volumes. And we're gonna come over here into volumes.
[00:01:22] Close all these, cuz I don't need them. And close that. And here we're gonna make a new file. This one is gonna be called index.js. And we're gonna make a new file here called Dockerfile. Surprise, surprise. And what we wanna do is we wanna create the worst database, where we're just gonna use the file system basically as a database.
[00:01:49] That anytime someone hits an endpoint, what we're gonna do is we're going to read the file, see what the number's inside the file, and then give it back to the user. So, again, I wrote the node code for you, so you don't necessarily have to worry what it is.
[00:02:04] So I come down here to volumes. And just copy all of this. You don't have to worry about anything in here. Nope, that's not a Docker file, that's an index.js. But just to walk you through it, fs stands for file system, path is a path resolution kind of module for node.
[00:02:27] And we're saying, write it to this data.txt file, okay? This isn't even a web server, right? So all this is gonna do, it's gonna run this on the Container and then it's gonna exit the container. So all it's gonna do is it's going to read from data.txt, which we're going to mount in via volume, right?
[00:02:51] And then it's going to add one to it. And then it's going to console log that. And then it's going to finish, right? So if this was just in an ephemeral container, right, it would always be one, right? Cuz it would just be run, okay, nothing's there. Here's one, exit, right?
[00:03:08] But I want it to maintain state, right? So I want it to be one, then two, then three, then four, right? So we're gonna use the volume to accomplish that. Does that make sense? Okay. So what we're gonna do now is we're gonna open our, Yeah, we're gonna make the simplest Docker file in the world here, which is FROM node:12-alpine.
[00:03:35] Doesn't matter, you can do scratch or whatever you want. I'm gonna say COPY --chown. Not from, c-h own. node:node./source. I'm going to say WORKDIR/src, and the command will be node index.js. Nothing new here, right? Pretty simple little Docker file. And then what we're gonna do now is we're gonna say, docker build --tag=incrementor.
[00:04:20] Built, awesome. docker run incrementor. So there it says, it says file not found, writing 0 to new file. Now if I run this again, what do you think will happen?
>> It'll read it [INAUDIBLE].
>> So it's gonna still stay 0 because we haven't mounted the volume in yet, right?
[00:04:41] So we keep running it, it's going to say, I can't find anything called data.txt, here you go, right? But what we can do now is we can use Docker run. And if you remember inside of our index.tht, let's make this a bit smaller for a second. We have the data path here, right?
[00:05:01] So this is how you read environmental variables inside of node. So I can modify this to be inside of a volume somewhere, right? So I'm gonna say docker run --, not there, --env, right? So this is how I'm gonna feed environmental variables into the container. DATA_PATH=/data/num.txt, okay? Then I'm going to say --mount type=volume.
[00:05:40] Src=, just make something up. I'm gonna call this incrementor data. As long as you're consistent you can call it whatever you want. And then target, we're gonna store that in /data, right? So that's where the actual volume's gonna be mounted right? And them I'm gonna say, incrementor, right?
[00:06:03] So I'm actually gonna run the container. So I was writing this demo earlier. But you can say docker volume list. God, I have a lot, don't I? docker volume rm incrementer data. I think that should remove it. Okay, so now if I run it. I must have gotten the wrong one.
[00:06:39] Let's do docker volume prune. That'll get rid of all of my volumes. Jeez, what did I claim? Well, I just got a gigabyte back, so that's neat. [LAUGH] All right, so now if I run this, it's gonna say 5. I don't even know where this anymore. So, Let's just call this incrementor data 2.
[00:07:09] So this will start a different one, and now it's saying writing 0 to a new file. And now if I run it again, it's gonna say 01. Cuz it console logs it and then increments it, right? That's why it says that. But that's how we're getting persistent state between runs, right?
[00:07:30] And so this is all volumes of data that Docker is gonna manage for you, right? So this hasn't exposed to my host. I think you can inspect it via the host, right? But it's not meant to, right? It's meant to be just for Docker containers. So that's kind of your rule of thumb.
[00:07:45] If you have information that's really just for the containers and it's never meant for the host, use volumes. Always prefer volumes over bind mounts. It's almost always a better idea to use volumes, the only reason to use bind mounts is if you specifically want some sort of host container interaction, like a dev container, or somewhere like the ngenx one that we use, right?
[00:08:07] That's where a bind mount's more applicable, where it's about that kind of communication between the host and the Docker container. Again, the primary use case here is, you'll see it with logs, right? So you'll have people writing out their logs to a volume, that's very common use case for that.
[00:08:23] You'll see it for databases, where people are keeping their database state, right, written out to volumes. There's various different ways that you can see that manifest. So the last three, or two, That we're not gonna talk about, but there are two other types of mounts. One of them is called temp Fs, which as the name belies, it's a temporary file system, right?
[00:08:56] So this is actually a Linux feature. So this only applies to Linux containers. You can actually mount in a temporary file system that then disappears at the end of it. And the reason that you would do this, that people like it, is they'll do it for their secrets, right?
[00:09:12] So if I have access password, and I have a database connection string or analytics key or something like that, I'll mount that in via temp Fs, which is this ephemeral Linux kernel feature of temporary mounting file system. So that's temp Fs, you'll see that for secrets almost exclusively.
[00:09:35] And there's another one called named pipes, or n pipe. I guess I haven't talked about it, there's Windows containers as well, right? So we've been doing everything on Linux containers, but there are also Windows containers, they work differently. Windows containers are actually full Windows virtualized operating systems, right?
[00:09:56] But you're just allowed to treat them like containers. So if you have a whole data center and it's managed by Kubernetes and they're all using containers everywhere, you can use Docker to manage Windows as well. And so there is a special file system for that called named pipes, which you can use for various other things with Windows containers.
[00:10:15] I've actually never even used Windows containers, so I'm not gonna explain any more than that. But they're out there, they exist, you can use them if you want to. All right, does anyone have any questions about volumes or bind mounts, either one? Make sense?
>> You said one of the main use cases would be a shared database or something that's external.
[00:10:38] Would you have a use case where you would want maybe different containers hitting the same volume to get a shared mock data between different instances running?
>> I could see that. I mean, that's another thing that volumes are quite useful for, is if I have Container A and container B.
[00:11:00] And they're both reading from a same dataset, a volume can be shared amongst both those. And so you can mount those both in. A dumb example I can think about that is, let's say I have five different web services and they're all running. And they're all logging out, and I want the logs to go to one place.
[00:11:14] I could mount the same logging volume into all five of them, right? And that would be a good way to accomplish that. Yeah, I could definitely see that. Or maybe you have one service that's writing logs to a mounted volume, and then you have a log analytic service, right?
[00:11:32] And that would be reading from that and displaying a nice dashboard or something like that. So, yeah, totally valid use case for that kind of stuff. And a good reason to use volumes.