- [Instructor] Now let's talk briefly about
how Docker accomplishes the idea of images and containers.
How does it do the storage behind them?
Keeping them isolated, letting them be stacked on top
of each other, all of that stuff requires
a little bit of an introduction
to the layers of the Unix file systems method.
So at the very lowest level you have actual things,
stuff that stores bits.
Hard drives, thumb drives, network storage devices,
things where you can set a value to one or zero
and it will remember it and you can come back later
and get it.
The kernel manages these.
On top of those it forms them into logical groups.
So you could say these four groups form a ray to ray,
or these two drives should be treated as one drive,
or this one drive should be treated as 432 drives.
So it has a layer that lets it sort of partition up
drives arbitrarily into groups
and then partition those groups up.
Docker makes extensive use of this capability.
On top of that we have file systems.
That determines which bits on the drive
are part of which part of while file.
So the fourth byte in the file foo dot text
would be at a particular spot on a particular drive
and it's up to the kernel with the file systems
to keep track of where that spot actually is.
Now on top of all that, you can take programs
and programs can pretend to be file systems.
We call this FUSE file systems.
So with that in mind the secret to Docker
and all of its images is COWs, all about COWs.
COW is an acronym in this case for copy on write.
So we start with our base image.
This is a cow.
He has no spots.
Now I want to write some spots for this cow.
Let's give him some dark spots.
You know, good traditional cow spots.
Instead of writing directly onto the cow
'cause someone else might be working with this cow,
there might another container running off of this image
right now, I don't wanna just reach in
and write some spots onto that image
because someone else is probably using it.
So I write my spots onto a separate layer right next to it.
And then when I start my container
layer the spots over the cow and give that to the container.
So the container sees the image of a cow with spots
even though the cow image still exists without his spots,
and others that are still using the spotless cow image
can continue to do so.
But I want these dark spots.
Now somebody else really has a more artistic perspective
and they'd like a cow with light spots.
So they're gonna start with the same image,
literally the same image, not a copy of the image
but the same one.
And they're gonna make their own layer
but with their own interpretation of what cow spots
should look like.
So they'll make their own file system layer
and layer it over that image.
And here we have a cow with different colored spots.
So it's called copy on write.
When I would write to this cow instead of writing
directly to the cow, I write to my own layer
which gets layered on top of the cow.
When I wanna look at the cow I just look at the whole thing.
I only copy the pieces that I write.
I read from the original and copy when you write,
copy on write.
So to get a little bigger perspective,
we have the original image of the cow unchanged
just one of them.
I'm gonna draw him down here.
We have the two resulting images of that cow
each one has a different set of spots layered on top of it.
So we have a total of one, two, three images here.
And two combinations of the way they're layered.
Docker has many different actual in kernel mechanisms
that it uses for managing the COW layers,
the copy on write file system layers.
And these depend a lot on what's available
on the system its running on.
Sometimes it uses BTRFS,
sometimes it uses LVM, the logical volume manager,
sometimes it uses the overlay file system.
There are many ways, it doesn't really matter
as long as it can accomplish layering
on its own sort.
You don't have to worry about the format of a COW
on one machine, a copy on write file system,
if you wanna import that image to another one
because what it does is it takes each layer,
splits out the layers and makes them into
normal GZIP files and ships them over the network
to you separately, and the receiving end of that
network connection, the place where you're actually
running the Docker server, receives all of those layers
separately and then puts them together
using the file systems that are available on that computer.
So this is how COWs can move easily between computers.
So the containers are independent of the storage engine.
I can send images between machines pretty much freely.
There is one little bit depending on the storage layer
that's in use on a particular machine.
It is possible in some cases to run out of layers.
Some of the storage engines have a limited number of layers
and others don't.
If you make a very deeply nested image on a machine
that allows a great number of layers,
and then you package it up and try to download it
on a machine that uses a storage engine with less layers,
you can run out of layers.
This is worth being vaguely aware of.
It doesn't come up very often
and it's good to be able to recognize it when it does.
Another part of images and storage in Docker
is how we do volumes and shared folders with the host.
These are not actually magic,
they're built right in to the Linux file system.
So the Linux file system starts with an assumed root
directory called slash.
Everything is slash something, slash home,
slash author, slash etsy, slash config file.
They all start with slash.
Slash is the root of the tree where it all starts.
You attach devices to various points along that tree.
You can also take a directory from anywhere
in the file system tree and just attach it somewhere else,
right on top of what's there.
Let's take a look at that.
To watch bind mounting in action I need a
convenient Linux system to show it in.
Well that's what Docker's for.
So I'm gonna go ahead and spin up
a Docker container to work in.
Now because I want to manipulate the file system
I'm going to need to exceed the default permissions
for a Docker container.
So I'm gonna have to pass the dash dash privileged
equals true to my container so that I get
a container that I can do this example in.
And as usual I'm gonna pass dash dash TI and RM
and let's run in ubuntu and bash.
Okay here I am in my container, let's make a directory.
MKDIR example, okay CD example.
Now that we're in our example directory it's brand new,
nothing's here, MKDIR work.
This will be my pretend work directory, CD work,
and I'm gonna do some work.
Work involves making files so I'm gonna make some files.
A B C D E and F, looking at them there they are.
Now I'm gonna head back to the base directory.
Now back in the base directory I'm gonna do some other work.
MKDIR other work, okay.
CD other work,
and I'm gonna create other A, other B,
other C, and other D.
Looking at them, there they are.
Now I'm gonna go back to the example directory.
Here I am in the example directory
and if I show all the files we see we have work
and other work with A B C D E F in work
and A other, B other, C other, D in other work.
Alright very straightforward here.
Now what I'm gonna do is I'm gonna run mount
to manipulate the file system, dash O bind
to say attach one directory on top of another.
Then other work on top of work.
Now if I do LS dash capital R to show all the files,
I see that other work contains other A B C D E
and work now has the contents of other work
layered on top of it, other A, other B, other C, other D.
Again, it didn't copy these.
It just took that directory that contained them
and attached it to the file system right on top
of the work directory.
It also didn't delete them, they're still there,
they're just presently covered up.
We can uncover them by running the U mount command
and unmounting work.
Okay, now if I do LS dash capital R again
we see everything is back the way it was.
They were just temporarily covered by another directory.
So there's an important side effect of this,
which is you have to get the mount order correct.
If you want to mount a folder and then a particular file
within that folder, you have to do in that order.
If you mount the file so it bind mounts that file
right onto that position, and then you mount the folder
on top of it, the file will be underneath the folder
and will be hidden.
So it's important to get the order of the dash V
for volume arguments to Docker correct.
Another bit is mounting volumes always mounts
the host's file system over the guest.
Docker doesn't give you a wave saying mount this guest
file system into the host preserving what was on the guest.
It always chooses to mount the host file system
over the guest file system.