Hello everyone! Today, we’re going to take a direct look at how Docker containers actually store and manage data, exploring their ‘magical’ structure firsthand.
Many people use containers, but often wonder where and how the actual files exist. Docker uses a technology called OverlayFS (Overlay Filesystem) to combine multiple layers, presenting them as if they were a single file system.
Today, instead of complex theories, we’ll directly type commands to thoroughly examine the internal structure of containers from the host OS perspective. Are you ready? π

1. Preparing the Experiment: Running a Container πββοΈ
First, let’s run a container for analysis. We’ll use the lightweight and fast nginx:alpine image.
# Run Nginx container (background mode)
docker run -d -p 80:80 --name nx nginx:alpine
Now Nginx is running in an isolated environment. However, from the Linux kernel’s perspective, this is just a single process.
2. Overlay’s Secret Map: Checking Mountinfo πΊοΈ
Now for the most crucial step! Let’s check how the file system this process sees is actually assembled, using the /proc file system.
# Query overlayfs settings from the mount information
mount | grep rootfs
Output example:
overlay on /var/lib/docker/rootfs/overlayfs/fea3c44e1dee873838bee303f32d739164f9a34e6a38b3c99ccc3c6e88f7e702 type overlay (rw,relatime,lowerdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/9/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/8/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/7/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/6/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/5/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/4/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/3/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/2/fs:/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/1/fs,upperdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/10/fs,workdir=/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/10/work,nouserxattr)
Executing this command will produce a rather long string, but you only need to find 4 key keywords here.
- π LowerDir (Image Layer): This is Read-Only. It contains the multiple layers that make up the nginx:alpine image we downloaded. It is never modified.
- βοΈ UpperDir (Container Layer): This is the Read-Write area. When you create or modify files inside the container, they are actually stored only here.
- βοΈ WorkDir: This is a temporary space internally used by OverlayFS for file merging operations.
- π Merged (Unified View): This is the path starting with /var/lib/docker/rootfs/overlayfs/ immediately following ‘overlay on’. It’s the final result we see, combining the LowerDir and UpperDir. This is the / (root) directory that the container sees.
3. ‘Teleporting’ from Host to Container Internals πͺ
Can we view container files from the host without connecting to the container (docker exec)? Yes, it’s possible! The Linux kernel has created a backdoor in the /proc directory.
# Method 1: Check Merged directory via Container ID
ls -al /var/lib/docker/rootfs/overlayfs/$(docker inspect -f '{{.Id}}' nx)
# Method 2: Directly navigate to the container's RootFS using PID (Recommended!)
ls -al /proc/$(docker inspect -f '{{.State.Pid}}' nx)/root/
The /proc/[PID]/root/ path is like a symbolic link to the root directory seen by that process. If you enter this path, you’ll see the exact same files as when you use `docker exec`. Isn’t that amazing? β¨
4. Data Writing Experiment and Verification π§ͺ
Are the host’s view and the container’s view truly connected? Let’s create a file on the host for testing.
# Create file in container's Root path from host
echo test1234 > /proc/$(docker inspect -f '{{.State.Pid}}' nx)/root/test.txt
Now, if you check inside the container, the test.txt file will magically appear. This experiment has significant implications: the container file system is not a separate, closed space, but rather a combination of specific paths from the host file system.
5. Where Are My Files Actually Located? πΎ
The test.txt file we just created must physically exist somewhere on the host’s hard drive. Where exactly was it stored?
# Find the actual physical location of test.txt file
find /var/lib/docker/rootfs/ -name test.txt
The search result will show a path like /var/lib/docker/overlay2/[hash_value]/diff/test.txt.
This path matches the UpperDir path we confirmed in step 3! In other words, we have directly verified the operating principle of OverlayFS: ‘the image (LowerDir) remains untouched, and all changes are stored separately in UpperDir’.
π― Conclusion and Summary
Through today’s practical session, we have learned the following facts:
- A container is not a magic box, but a Linux process.
- A container’s file system is a Merged view, combining a Read-Only image (Lower) with a Read-Write layer (Upper) on top.
- When a container is deleted, its UpperDir is also deleted, and any data written within it is lost. (This is why volumes are necessary!)
Understanding these principles will help you better grasp why Docker’s image build speed and container startup speed are fast, and how to manage storage effectively.
Have a great container journey today! β΅οΈ
Leave a Reply