Exploring Docker container's file system

LinuxDockerFilesystems

Linux Problem Overview


I've noticed with docker that I need to understand what's happening inside a container or what files exist in there. One example is downloading images from the docker index - you don't have a clue what the image contains so it's impossible to start the application.

What would be ideal is to be able to ssh into them or equivalent. Is there a tool to do this, or is my conceptualisation of docker wrong in thinking I should be able to do this.

Linux Solutions


Solution 1 - Linux

Here are a couple different methods...

A) Use docker exec (easiest)

Docker version 1.3 or newer supports the command exec that behave similar to nsenter. This command can run new process in already running container (container must have PID 1 process running already). You can run /bin/bash to explore container state:

docker exec -t -i mycontainer /bin/bash

see Docker command line documentation

B) Use Snapshotting

You can evaluate container filesystem this way:

# find ID of your running container:
docker ps

# create image (snapshot) from container filesystem
docker commit 12345678904b5 mysnapshot

# explore this filesystem using bash (for example)
docker run -t -i mysnapshot /bin/bash

This way, you can evaluate filesystem of the running container in the precise time moment. Container is still running, no future changes are included.

You can later delete snapshot using (filesystem of the running container is not affected!):

docker rmi mysnapshot
C) Use ssh

If you need continuous access, you can install sshd to your container and run the sshd daemon:

 docker run -d -p 22 mysnapshot /usr/sbin/sshd -D
 
 # you need to find out which port to connect:
 docker ps

This way, you can run your app using ssh (connect and execute what you want).

D) Use nsenter

Use nsenter, see Why you don't need to run SSHd in your Docker containers

> The short version is: with nsenter, you can get a shell into an > existing container, even if that container doesn’t run SSH or any kind > of special-purpose daemon

Solution 2 - Linux

UPDATE: EXPLORING!

This command should let you explore a running docker container:

docker exec -it name-of-container bash

The equivalent for this in docker-compose would be:

docker-compose exec web bash

(web is the name-of-service in this case and it has tty by default.)

Once you are inside do:

ls -lsa

or any other bash command like:

cd ..

This command should let you explore a docker image:

docker run --rm -it --entrypoint=/bin/bash name-of-image

once inside do:

ls -lsa

or any other bash command like:

cd ..

The -it stands for interactive... and tty.


This command should let you inspect a running docker container or image:

docker inspect name-of-container-or-image

You might want to do this and find out if there is any bash or sh in there. Look for entrypoint or cmd in the json return.

NOTE: This answer relies on commen tool being present, but if there is no bash shell or common tools like ls present you could first add one in a layer if you have access to the Dockerfile: example for alpine:

RUN apk add --no-cache bash

Otherwise if you don't have access to the Dockerfile then just copy the files out of a newly created container and look trough them by doing:

docker create <image>  # returns container ID the container is never started.
docker cp <container ID>:<source_path> <destination_path>
docker rm <container ID>
cd <destination_path> && ls -lsah

see docker exec documentation

see docker-compose exec documentation

see docker inspect documentation

see docker create documentation

Solution 3 - Linux

In case your container is stopped or doesn't have a shell (e.g. hello-world mentioned in the installation guide, or non-alpine traefik), this is probably the only possible method of exploring the filesystem.

You may archive your container's filesystem into tar file:

docker export adoring_kowalevski > contents.tar

Or list the files:

docker export adoring_kowalevski | tar t

Do note, that depending on the image, it might take some time and disk space.

Solution 4 - Linux

Before Container Creation :

If you to explore the structure of the image that is mounted inside the container you can do

sudo docker image save image_name > image.tar
tar -xvf image.tar

This would give you the visibility of all the layers of an image and its configuration which is present in json files.

After container creation :

For this there are already lot of answers above. my preferred way to do this would be -

docker exec -t -i container /bin/bash

Solution 5 - Linux

The file system of the container is in the data folder of docker, normally in /var/lib/docker. In order to start and inspect a running containers file system do the following:

hash=$(docker run busybox)
cd /var/lib/docker/aufs/mnt/$hash

And now the current working directory is the root of the container.

Solution 6 - Linux

The most upvoted answer is working for me when the container is actually started, but when it isn't possible to run and you for example want to copy files from the container this has saved me before:

docker cp <container-name>:<path/inside/container> <path/on/host/>

Thanks to docker cp (link) you can copy directly from the container as it was any other part of your filesystem. For example, recovering all files inside a container:

mkdir /tmp/container_temp
docker cp example_container:/ /tmp/container_temp/

Note that you don't need to specify that you want to copy recursively.

Solution 7 - Linux

you can use dive to view the image content interactively with TUI

https://github.com/wagoodman/dive

enter image description here

Solution 8 - Linux

Try using

docker exec -it <container-name> /bin/bash

There might be possibility that bash is not implemented. for that you can use

docker exec -it <container-name> sh

Solution 9 - Linux

On Ubuntu 14.04 running Docker 1.3.1, I found the container root filesystem on the host machine in the following directory:

/var/lib/docker/devicemapper/mnt/<container id>/rootfs/

Full Docker version information:

Client version: 1.3.1
Client API version: 1.15
Go version (client): go1.3.3
Git commit (client): 4e9bbfa
OS/Arch (client): linux/amd64
Server version: 1.3.1
Server API version: 1.15
Go version (server): go1.3.3
Git commit (server): 4e9bbfa

Solution 10 - Linux

In my case no shell was supported in container except sh. So, this worked like a charm

docker exec -it <container-name> sh

Solution 11 - Linux

I use another dirty trick that is aufs/devicemapper agnostic.

I look at the command that the container is running e.g. docker ps and if it's an apache or java i just do the following:

sudo -s
cd /proc/$(pgrep java)/root/

and voilá you're inside the container.

Basically you can as root cd into /proc/<PID>/root/ folder as long as that process is run by the container. Beware symlinks will not make sense wile using that mode.

Solution 12 - Linux

The most voted answer is good except if your container isn't an actual Linux system.

Many containers (especially the go based ones) don't have any standard binary (no /bin/bash or /bin/sh). In that case, you will need to access the actual containers file directly:

Works like a charm:

name=<name>
dockerId=$(docker inspect -f {{.Id}} $name)
mountId=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$dockerId/mount-id)
cd /var/lib/docker/aufs/mnt/$mountId

Note: You need to run it as root.

Solution 13 - Linux

Only for LINUX

The most simple way that I use was using proc dir, the container must be running in order to inspect the docker container files.

  1. Find out the process id (PID) of the container and store it into some variable

    > PID=$(docker inspect -f '{{.State.Pid}}' your-container-name-here)

  2. Make sure the container process is running, and use the variable name to get into the container folder

    > cd /proc/$PID/root

If you want to get through the dir without finding out the PID number, just use this long command

cd /proc/$(docker inspect -f '{{.State.Pid}}' your-container-name-here)/root

Tips:

After you get inside the container, everything you do will affect the actual process of the container, such as stopping the service or changing the port number.

Hope it helps

Note:

This method only works if the container is still running, otherwise, the directory wouldn't exist anymore if the container has stopped or removed

Solution 14 - Linux

None of the existing answers address the case of a container that exited (and can't be restarted) and/or doesn't have any shell installed (e.g. distroless ones). This one works as long has you have root access to the Docker host.

For a real manual inspection, find out the layer IDs first:

docker inspect my-container | jq '.[0].GraphDriver.Data'

In the output, you should see something like

"MergedDir": "/var/lib/docker/overlay2/03e8df748fab9526594cfdd0b6cf9f4b5160197e98fe580df0d36f19830308d9/merged"

Navigate into this folder (as root) to find the current visible state of the container filesystem.

Solution 15 - Linux

On newer versions of Docker you can run docker exec [container_name] which runs a shell inside your container

So to get a list of all the files in a container just run docker exec [container_name] ls

Solution 16 - Linux

I wanted to do this, but I was unable to exec into my container as it had stopped and wasn't starting up again due to some error in my code.

What worked for me was to simply copy the contents of the entire container into a new folder like this:

docker cp container_name:/app/ new_dummy_folder

I was then able to explore the contents of this folder as one would do with a normal folder.

Solution 17 - Linux

This will launch a bash session for the image:

docker run --rm -it --entrypoint=/bin/bash

Solution 18 - Linux

For me, this one works well (thanks to the last comments for pointing out the directory /var/lib/docker/):

chroot /var/lib/docker/containers/2465790aa2c4*/root/

Here, 2465790aa2c4 is the short ID of the running container (as displayed by docker ps), followed by a star.

Solution 19 - Linux

For docker aufs driver:

The script will find the container root dir(Test on docker 1.7.1 and 1.10.3 )

if [ -z "$1" ] ; then
 echo 'docker-find-root $container_id_or_name '
 exit 1
fi
CID=$(docker inspect   --format {{.Id}} $1)
if [ -n "$CID" ] ; then
	if [ -f  /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id ] ; then
		F1=$(cat /var/lib/docker/image/aufs/layerdb/mounts/$CID/mount-id)
	   d1=/var/lib/docker/aufs/mnt/$F1
	fi
	if [ ! -d "$d1" ] ; then
		d1=/var/lib/docker/aufs/diff/$CID
	fi
	echo $d1
fi

Solution 20 - Linux

This answer will help those (like myself) who want to explore the docker volume filesystem even if the container isn't running.

List running docker containers:

docker ps

=> CONTAINER ID "4c721f1985bd"

Look at the docker volume mount points on your local physical machine (https://docs.docker.com/engine/tutorials/dockervolumes/):

docker inspect -f {{.Mounts}} 4c721f1985bd

=> [{ /tmp/container-garren /tmp true rprivate}]

This tells me that the local physical machine directory /tmp/container-garren is mapped to the /tmp docker volume destination.

Knowing the local physical machine directory (/tmp/container-garren) means I can explore the filesystem whether or not the docker container is running. This was critical to helping me figure out that there was some residual data that shouldn't have persisted even after the container was not running.

Solution 21 - Linux

For an already running container, you can do:

dockerId=$(docker inspect -f {{.Id}} [docker_id_or_name])

cd /var/lib/docker/btrfs/subvolumes/$dockerId

You need to be root in order to cd into that dir. If you are not root, try 'sudo su' before running the command.

Edit: Following v1.3, see Jiri's answer - it is better.

Solution 22 - Linux

another trick is to use the atomic tool to do something like:

mkdir -p /path/to/mnt && atomic mount IMAGE /path/to/mnt

The Docker image will be mounted to /path/to/mnt for you to inspect it.

Solution 23 - Linux

If you are using Docker v19.03, you follow the below steps.

# find ID of your running container:

  docker ps

# create image (snapshot) from container filesystem
  
  docker commit 12345678904b5 mysnapshot

# explore this filesystem 
  
  docker run -t -i mysnapshot /bin/sh

Solution 24 - Linux

My preferred way to understand what is going on inside container is:

  1. expose -p 8000

     docker run -it -p 8000:8000 image
    
  2. Start server inside it

     python -m SimpleHTTPServer
    

Solution 25 - Linux

If you are using the AUFS storage driver, you can use my docker-layer script to find any container's filesystem root (mnt) and readwrite layer :

# docker-layer musing_wiles
rw layer : /var/lib/docker/aufs/diff/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f
mnt      : /var/lib/docker/aufs/mnt/c83338693ff190945b2374dea210974b7213bc0916163cc30e16f6ccf1e4b03f

Edit 2018-03-28 :
docker-layer has been replaced by docker-backup

Solution 26 - Linux

The docker exec command to run a command in a running container can help in multiple cases.

Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

Run a command in a running container

Options: -d, --detach Detached mode: run command in the background --detach-keys string Override the key sequence for detaching a container -e, --env list Set environment variables -i, --interactive Keep STDIN open even if not attached --privileged Give extended privileges to the command -t, --tty Allocate a pseudo-TTY -u, --user string Username or UID (format: [:]) -w, --workdir string Working directory inside the container

For example :

  1. Accessing in bash to the running container filesystem :

    docker exec -it containerId bash

  2. Accessing in bash to the running container filesystem as root to be able to have required rights :

    docker exec -it -u root containerId bash

This is particularly useful to be able to do some processing as root in a container.

  1. Accessing in bash to the running container filesystem with a specific working directory :

    docker exec -it -w /var/lib containerId bash

Solution 27 - Linux

Often times I only need to explore the docker filesystem because my build won't run, so docker run -it <container_name> bash is impractical. I also do not want to waste time and memory copying filesystems, so docker cp <container_name>:<path> <target_path> is impractical too.

While possibly unorthodox, I recommend re-building with ls as the final command in the Dockerfile:

CMD [ "ls", "-R" ]

Solution 28 - Linux

You can run a bash inside the container with this:

$ docker run -it ubuntu /bin/bash

Solution 29 - Linux

Practically all containers I use have Python, so I attach to the container,

pip install jupyterlab
cd /
jupyter lab --allow-root

I ^click the link that the Jupyter Lab server offers and in the host's browser I have the perfect GUI for the file system and can open all kinds of files (ipnb, py, md (in preview),...)

Cheers
G.

Solution 30 - Linux

I've found the easiest, all-in-one solution to View, Edit, Copy files with a GUI app inside almost any running container.

mc editing files in docker

  1. inside the container install mc and ssh: docker exec -it <container> /bin/bash, then with prompt install mc and ssh packages
  2. in same exec-bash console, run mc
  3. press ESC then 9 then ENTER to open menu and select "Shell link..."
  4. using "Shell link..." open SCP-based filesystem access to any host with ssh server running (including the one running docker) by it's IP address
  5. do your job in graphical UI

this method overcomes all issues with permissions, snap isolation etc., allows to copy directly to any machine and is the most pleasant to use for me

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser2668128View Question on Stackoverflow
Solution 1 - LinuxJiriView Answer on Stackoverflow
Solution 2 - LinuxKhalil GharbaouiView Answer on Stackoverflow
Solution 3 - LinuxIlya Murav'jovView Answer on Stackoverflow
Solution 4 - LinuxGaurav IngalkarView Answer on Stackoverflow
Solution 5 - LinuxRovanionView Answer on Stackoverflow
Solution 6 - LinuxJulius PrintzView Answer on Stackoverflow
Solution 7 - LinuxAndy WongView Answer on Stackoverflow
Solution 8 - LinuxGaurav SharmaView Answer on Stackoverflow
Solution 9 - LinuxpiercebotView Answer on Stackoverflow
Solution 10 - LinuxshxView Answer on Stackoverflow
Solution 11 - LinuxtelamonView Answer on Stackoverflow
Solution 12 - LinuxFlorentView Answer on Stackoverflow
Solution 13 - LinuxAditya Kresna PermanaView Answer on Stackoverflow
Solution 14 - LinuxRaphaelView Answer on Stackoverflow
Solution 15 - LinuxxrhView Answer on Stackoverflow
Solution 16 - Linuxflyer2403View Answer on Stackoverflow
Solution 17 - LinuxLeYAUableView Answer on Stackoverflow
Solution 18 - LinuxdashohoxhaView Answer on Stackoverflow
Solution 19 - LinuxqxoView Answer on Stackoverflow
Solution 20 - LinuxGarren SView Answer on Stackoverflow
Solution 21 - LinuxAlonLView Answer on Stackoverflow
Solution 22 - LinuxGiuseppe ScrivanoView Answer on Stackoverflow
Solution 23 - Linuxsaurabh tiwariView Answer on Stackoverflow
Solution 24 - LinuxkgneteView Answer on Stackoverflow
Solution 25 - LinuxVinceView Answer on Stackoverflow
Solution 26 - LinuxdavidxxxView Answer on Stackoverflow
Solution 27 - Linuxtim-montagueView Answer on Stackoverflow
Solution 28 - LinuxYang YuView Answer on Stackoverflow
Solution 29 - Linuxgue22View Answer on Stackoverflow
Solution 30 - LinuxgrandrewView Answer on Stackoverflow