Where are Docker Images Stored? Docker Container Paths Explained

Docker has revolutionized how developers package and deploy applications. By bundling code and dependencies into portable images, Docker makes it easy to build, ship, and run distributed applications at scale. But have you ever wondered where Docker actually stores all this data under the hood?

In this in-depth guide, we‘ll peel back the layers of Docker storage and take a closer look at where Docker images and containers live on your filesystem. Whether you‘re a beginner just getting started with Docker or a seasoned pro looking to optimize your storage, understanding the Docker directory structure is key to unleashing the full power of containers.

Docker Images vs. Containers

Before we dive into storage details, let‘s clarify some terminology. In Docker, an image is a read-only template used to spin up containers. It‘s defined by a Dockerfile and contains the application code, libraries, tools, and a base OS. A container is a runnable instance of an image. You can create, start, stop, and delete containers while the image remains unchanged.

When you run a container, Docker creates a thin writable layer on top of the image layers where any changes are stored. This allows multiple containers to share access to the same underlying image, keeping storage requirements lean. With that context in mind, let‘s see where Docker keeps all these bits and bytes.

The Docker Root Directory

By default, Docker stores all persistent data in a single directory known as the Docker root. The location depends on your host operating system:

  • Linux: /var/lib/docker/
  • Windows: C:\ProgramData\DockerDesktop\
  • macOS: ~/Library/Containers/com.docker.docker/Data/vms/0/

On Linux, /var/lib/docker/ contains subdirectories for various types of Docker data:

$ ls -l /var/lib/docker/
total 14
drwx------  2 root root 4096 Feb  3 12:22 containers/
drwx------  4 root root 4096 Feb  3 12:22 image/
drwxr-x---  3 root root 4096 Feb  3 12:22 network/
drwx------  6 root root 4096 Feb  3 12:22 overlay2/
drwx------  4 root root 4096 Feb  3 12:22 plugins/
drwx------  2 root root 4096 Feb  3 12:22 swarm/
drwx------  2 root root 4096 Feb  3 12:22 tmp/
drwx------ 11 root root 4096 Feb  3 12:22 volumes/

The overlay2/ directory is where Docker stores the actual contents of images and containers, assuming you‘re using the default overlay2 storage driver (more on that later). Let‘s take a closer look inside.

Inspecting Image Layers

Each Docker image consists of a stack of read-only layers. When you build an image, Docker saves each layer in the overlay2/ directory under a unique random ID. You can inspect an image‘s layers with the docker image inspect command:

$ docker image inspect node:lts
[
    {
        "Id": "sha256:c1d02ac1d9b4...",
        ...
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/f18c714e36ba1.../diff:/var/lib/docker/overlay2/2a04ea231bbb8.../diff",
                "MergedDir": "/var/lib/docker/overlay2/2a96c36171b21.../merged", 
                "UpperDir": "/var/lib/docker/overlay2/2a96c36171b21.../diff",
                "WorkDir": "/var/lib/docker/overlay2/2a96c36171b21.../work"
            },
            "Name": "overlay2"
        }
    }
]

Here we can see that the node:lts image consists of two read-only layers stacked on top of each other, as referenced by the LowerDir paths. The MergedDir contains the unified filesystem visible inside a running container, while the UpperDir stores any changes made in the container‘s writable layer.

Exploring Container Filesystems

Speaking of container storage, each container gets its own directory under containers/ named after the container ID:

$ docker run -d --name myapp node:lts
2aace14f59dba7a0e80222c2b5da39fa70f03a797f058226d6cba7bb6bac8a18

$ ls -l /var/lib/docker/containers/2aace14f59dba7a0e80222c2b5da39fa70f03a797f058226d6cba7bb6bac8a18/  
total 4
-rw-r----- 1 root root  379 Feb  8 23:31 config.v2.json
-rw-r--r-- 1 root root 1410 Feb  8 23:28 hostconfig.json
-rw-r----- 1 root root   13 Feb  8 23:28 hostname
-rw-r----- 1 root root  174 Feb  8 23:28 hosts
-rw-r----- 1 root root  183 Feb  8 23:11 resolv.conf
-rw-r--r-- 1 root root   71 Feb  8 23:28 resolv.conf.hash
drwxr-xr-x 2 root root   60 Feb  8 23:28 secrets/
-rw-r--r-- 1 root root  217 Feb  8 23:28 version.json 

The container directory contains metadata files like config.v2.json, hostconfig.json, etc. To see the actual container filesystem, look for the MergedDir path in the config.v2.json file — this matches the path in the docker image inspect output shown earlier.

Any changes made inside a running container, like creating new files or modifying existing ones, are stored in the container‘s UpperDir. When the container is deleted, the UpperDir is removed while the underlying image layers remain untouched.

Managing Docker Volumes

For persistent data that needs to outlive containers, Docker uses volumes. A volume is a directory in the Docker root specially designated to store data outside the Union File System.

When you create a named volume, Docker generates a random directory under volumes/ to hold the volume data:

$ docker volume create mydata
mydata

$ docker volume inspect mydata
[
    {
        "CreatedAt": "2023-02-08T19:19:42-05:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
        "Name": "mydata",
        "Options": {},
        "Scope": "local"
    }
]

You can then mount the volume into a container at a specified path using the -v flag:

$ docker run -d -v mydata:/app/data myapp

Now any files written to /app/data inside the container will be persisted in the host‘s /var/lib/docker/volumes/mydata/_data directory. Volumes can be shared between containers and will remain even when the containers are removed.

Cleaning Up Docker Storage

Over time, Docker‘s storage footprint can grow quite large, especially if you‘re frequently building images and spinning up containers. To reclaim space, you can use Docker‘s built-in prune commands:

# Remove all unused images, not just dangling ones 
$ docker image prune -a

# Remove stopped containers
$ docker container prune

# Remove all unused local volumes
$ docker volume prune  

For more granular cleanup, you can remove individual images, containers and volumes using the docker image rm, docker container rm and docker volume rm commands respectively. Just be careful not to remove anything you still need!

Advanced Docker Storage Topics

We‘ve covered the basics of Docker storage, but there‘s plenty more to explore:

  • Storage drivers: Docker supports multiple pluggable storage drivers for different use cases, like aufs, devicemapper, btrfs, and zfs, in addition to the default overlay2 driver.
  • Volume mounts: In addition to Docker volumes, you can mount host directories or cloud storage directly into containers for more flexible data sharing.
  • Multi-stage builds: Split your image build into multiple stages to keep the final image lean and secure. Intermediate build stages can use their own storage.
  • Remote storage: Docker has plumbing to store images on remote registries and support for volume plugins to integrate with external storage systems.

I encourage you to dig into the official Docker storage documentation to learn about these more advanced topics.

Conclusion

We‘ve taken a deep dive into the internals of Docker storage, from the high-level concepts of images and containers to the nitty-gritty details of the Docker root directory layout. Understanding where Docker stores persistent vs. ephemeral data is key to designing robust containerized applications.

The key takeaways are:

  1. Docker images are stored as read-only layers under /var/lib/docker/<storage-driver>/.
  2. Containers get a thin writable layer on top of the image layers.
  3. Use volumes mounted into containers to persist data outside the Union File System.
  4. Regularly prune unused Docker resources to keep storage usage in check.

I hope this guide has demystified Docker storage and prepared you to set sail on your container journey with confidence! Feel free to reach out with any questions. Happy containerizing!

References

Similar Posts