How to Explore a Docker Container's File System: View Files, Understand Image Contents, and Access Without SSH
Date Updated
Docker containers have revolutionized how applications are packaged and deployed, offering isolation, consistency, and portability. However, when debugging misconfigurations, verifying file placements, or understanding how an image is structured, you’ll often need to peek inside a container’s file system. Unlike traditional VMs, containers are lightweight and ephemeral, so SSH isn’t the right tool (and is often disabled by design).
In this guide, we’ll explore practical, SSH-free methods to inspect container file systems—whether the container is running, stopped, or even just an image. We’ll cover basic commands, advanced tools, and best practices to avoid common pitfalls. By the end, you’ll confidently navigate container internals to debug, audit, or learn how your images are built.
Prerequisites#
- Basic familiarity with Docker (e.g.,
docker run,docker pscommands). - Docker Engine installed (v20.10+ recommended for latest features like ephemeral containers).
- Terminal access to a system with Docker (Linux, macOS, or Windows with WSL2).
Table of Contents#
- Understanding Docker’s File System Basics
- Container vs. Image File Systems
- Union File System (UnionFS) Primer
- Method 1: Explore a Running Container’s File System
- Using
docker execto Access a Shell - Using
docker cpto Copy Files Out - Using
docker runwith Interactive Shell (Ephemeral Containers)
- Using
- Method 2: Explore a Stopped Container or Image
- Using
docker exportto Extract the File System - Using
docker image inspectto View Image Layers - Mounting an Image/Container as a Local Directory (Advanced)
- Using
- Advanced Techniques: Tools for Deep Exploration
- Dive: Analyze Image Layers Visually
- CTOP: Monitor Container File System Activity
- Using
nsenterto Access the Container Namespace
- Best Practices for Exploring Container File Systems
- Troubleshooting Common Issues
- Conclusion
- References
Understanding Docker’s File System Basics#
Before diving into tools, let’s clarify how Docker manages file systems. This foundational knowledge will help you interpret what you see when exploring containers.
Container vs. Image File Systems#
- Docker Images: Read-only templates built from layers. Each layer represents a command in the
Dockerfile(e.g.,COPY,RUN). Layers are cached to speed up builds. - Docker Containers: Runtime instances of images. Containers add a single writable layer on top of the image’s read-only layers. Changes to files in a container (e.g., log files, config edits) are stored in this writable layer (and are lost when the container is deleted, unless persisted with volumes).
Union File System (UnionFS) Primer#
Docker uses a Union File System (e.g., Overlay2, AUFS) to merge the read-only image layers and the container’s writable layer into a single, unified file system. This “stacking” allows containers to share image layers (saving disk space) while maintaining isolation.
Example: If an image has a layer with /app/config.ini, and the container modifies that file, UnionFS creates a copy of config.ini in the writable layer. The original in the image layer remains unchanged.
Method 1: Explore a Running Container’s File System#
For running containers, Docker provides built-in commands to interact with the file system directly.
Using docker exec to Access a Shell#
The most common way to explore a running container is to spawn an interactive shell inside it using docker exec.
Steps:#
-
List running containers to get the container name or ID:
docker ps # Output example: # CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # abc123 nginx:alpine "/docker-entrypoint.sh nginx -g 'daemon off;'" 5m ago Up 5m 80/tcp my-nginx -
Start an interactive shell in the container:
Use-itfor interactive mode (keeps STDIN open and allocates a pseudo-TTY). Replace<container>with the name or ID (e.g.,my-nginx):docker exec -it <container> /bin/sh-
If the container has
bash(e.g., Debian/Ubuntu images), use/bin/bashinstead:docker exec -it <container> /bin/bash -
Note: Minimal images (e.g., Alpine) may only have
sh(notbash). If you get an error like/bin/bash: not found, use/bin/sh.
-
-
Explore the file system once inside the shell:
Use standard Unix commands likels,cd,cat,nano, orvi(if installed) to navigate:# Example: Check Nginx config in an nginx container cd /etc/nginx cat nginx.conf
Using docker cp to Copy Files Out#
If you need to analyze a file locally (e.g., parse logs, check permissions), use docker cp to copy files/directories from the container to your host machine.
Syntax:#
docker cp <container>:/path/to/container/file /path/on/host Example:#
Copy Nginx’s access log from a running container to your host’s ~/container-logs directory:
# Create a local directory (if needed)
mkdir -p ~/container-logs
# Copy the log file
docker cp my-nginx:/var/log/nginx/access.log ~/container-logs/
# Verify on host
cat ~/container-logs/access.log Tip: Use docker exec to first list files (e.g., docker exec my-nginx ls /var/log/nginx) to confirm paths before copying.
Using docker run with Interactive Shell (Ephemeral Containers)#
If you want to explore an image without starting a long-running container (e.g., testing a new image), use docker run with --rm (auto-delete after exit) and an interactive shell.
Syntax:#
docker run --rm -it <image> /bin/sh Example:#
Explore the alpine:latest image without persisting the container:
docker run --rm -it alpine:latest /bin/sh
# Inside the shell, explore:
ls / # List root directory
cat /etc/os-release # Check OS details --rm: Ensures the container is deleted after you exit the shell (avoids clutter).-it: Enables interactive mode (critical for shell access).
Method 2: Explore a Stopped Container or Image#
What if the container isn’t running (e.g., it crashed) or you want to inspect an image directly? Use these methods.
Using docker export to Extract the File System#
docker export creates a tarball of a container’s entire file system (including the writable layer). This works even if the container is stopped.
Steps:#
-
List all containers (including stopped ones):
docker ps -a -
Export the container’s file system to a tarball:
docker export <container> > container-fs.tar -
Extract the tarball to explore locally:
mkdir container-fs tar -xf container-fs.tar -C container-fs # Explore the extracted files cd container-fs ls / # View the container's root directory
Caveat: docker export does not preserve layer metadata (e.g., which files came from the image vs. the writable layer). For layer-specific analysis, use docker image inspect (below).
Using docker image inspect to View Image Layers#
To understand how an image is structured (e.g., which layers contain specific files), use docker image inspect to list layers and their contents.
Step 1: Get Image Layer Hashes#
Images are built from a stack of layers. Use inspect to list these layers:
docker image inspect --format '{{.RootFS.Layers}}' <image>
# Example output (truncated):
# [sha256:abc123... sha256:def456...] Step 2: Explore Layer Contents#
Docker stores layers on the host under /var/lib/docker/overlay2/ (default for Overlay2 storage driver). Each layer hash maps to a directory here.
Example: Explore the first layer of nginx:alpine:
# Get the first layer hash (from the earlier command)
LAYER_HASH=sha256:abc123...
# Navigate to the layer's directory (may require root)
sudo ls /var/lib/docker/overlay2/$LAYER_HASH/diff Note: Modifying these files directly can corrupt images—use this only for inspection!
Mounting an Image/Container as a Local Directory (Advanced)#
For advanced users, mount the container/image file system directly to the host using tools like guestfish (for images) or mount (for containers).
Example: Mount a Container’s Writable Layer#
-
Find the container’s mount point with
docker inspect:docker inspect -f '{{.GraphDriver.Data.MergedDir}}' <container> # Output: /var/lib/docker/overlay2/xyz123/merged -
Mount this directory to a local path (requires root):
sudo mount --bind /var/lib/docker/overlay2/xyz123/merged /mnt/container-fs # Explore the mounted directory ls /mnt/container-fs
Warning: This bypasses Docker’s isolation—use with extreme caution!
Advanced Techniques: Tools for Deep Exploration#
For complex scenarios (e.g., visualizing layers, monitoring file activity), use these third-party tools.
Dive: Analyze Image Layers Visually#
Dive is a CLI tool that lets you explore image layers interactively, showing which files each layer adds/modifies.
Installation (via Docker):#
docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock wagoodman/dive <image> Usage:#
- Navigate layers with arrow keys.
- See file size changes between layers.
- Identify bloat (e.g., unnecessary files in layers).
CTOP: Monitor Container File System Activity#
CTOP is a top-like tool for containers, including file system I/O metrics.
Installation:#
# Linux/macOS
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-linux-amd64 -O /usr/local/bin/ctop
sudo chmod +x /usr/local/bin/ctop
# Run
ctop - Press
fto filter by container. - View read/write rates under the “IO” column.
Using nsenter to Access the Container Namespace#
For low-level access (e.g., if docker exec fails), use nsenter to enter the container’s Linux namespace directly.
Steps:#
-
Get the container’s PID:
docker inspect -f '{{.State.Pid}}' <container> # Output: 12345 -
Enter the container’s mount namespace (requires root):
sudo nsenter --target 12345 --mount --uts --ipc --net --pid /bin/sh
- This gives you root access to the container’s file system, bypassing Docker’s CLI.
Best Practices for Exploring Container File Systems#
-
Avoid Modifying Container Files Directly
Container file systems are ephemeral—changes are lost when the container restarts. Use volumes or bind mounts for persistent changes. -
Use Ephemeral Containers for Exploration
Always add--rmwhen running exploration containers (e.g.,docker run --rm -it <image> sh) to avoid cluttering your system. -
Clean Up After Exploration
Delete exported tarballs (rm container-fs.tar), mounted directories, and stopped containers (docker rm <container>) to free disk space. -
Prefer
docker execOver Raw Namespace Access
Tools likensenterare powerful but risky—stick todocker execunless absolutely necessary.
Troubleshooting Common Issues#
"Container Not Running" Error with docker exec#
- Fix: Start the container first with
docker start <container>, or usedocker runto create a new interactive container from the image.
Permission Denied When Accessing Files#
- Cause: The container’s user (e.g., non-root) lacks access, or the host user can’t read copied files.
- Fix:
- Run
docker execas root:docker exec -u root -it <container> /bin/sh. - Use
sudowhen copying files to the host:sudo docker cp <container>:/file /host/path.
- Run
Corrupted File System#
- Cause: Container crashed due to disk errors or invalid writes.
- Fix: Inspect logs with
docker logs <container>, then recreate the container from the image:docker rm <container> && docker run <image>.
Conclusion#
Exploring a Docker container’s file system is critical for debugging, auditing, and understanding image structure—no SSH required. Whether using docker exec for running containers, docker export for stopped ones, or tools like Dive for layer analysis, you now have the tools to navigate container internals confidently.
Remember: Containers are ephemeral by design, so prioritize exploration over modification. Use ephemeral containers, clean up clutter, and leverage Docker’s built-in commands before reaching for advanced tools like nsenter.