Explore Docker's image files if container exit

2020-02-15 02:44发布

问题:

I have a Docker image that I pulled from Docker hub.

When I run docker run image_name, container exits immediately.

I don't have access to the source code of the Docker image, including Dockerfile. All I have is an image I pulled from hub.docker.com.

I need to debug/see what is inside the image (e.g. see and explore image's filesystem), without running it as a container.

Is it possible?

回答1:

Start a container from desired image like this:

docker run -it --rm image_name bash

-i Keeps STDIN open even if not attached

-t Allocates a pseudo-tty

--rm prunes stopped container after exit

bash executes the specific command in the container. You can execute any valid command.

Example docker run -it --rm centos:7 pwd outputs / (root directory).

Update: In some cases, where image's entrypoint uses bash/sh -c format above command(docker run -it --rm image_name bash) will not work because bash will be treated as additional argument to image's orignal entrypoint.

In such case you can use the --entrypoint flag for achieving the same result:

docker run -it --entrypoint "/bin/bash" image_name


回答2:

Another approach to see "inside" without having to run a container would be:

docker image history <your image name>

See the docs here.

This doesn't give you the option to list directories and files but you can get a first picture of what's inside without running a container (which might be risky if the owner has published a malicious image).

Example with the nginx:latest image:

$ docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
f17d81b4b692: Pull complete 
d5c237920c39: Pull complete 
a381f92f36de: Pull complete 
Digest: sha256:b73f527d86e3461fd652f62cf47e7b375196063bbbd503e853af5be16597cb2e
Status: Downloaded newer image for nginx:latest

$ docker image history nginx
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
dbfc48660aeb        13 days ago         /bin/sh -c #(nop)  CMD ["nginx" "-g" "daemon…   0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  STOPSIGNAL [SIGTERM]         0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  EXPOSE 80/tcp                0B                  
<missing>           13 days ago         /bin/sh -c ln -sf /dev/stdout /var/log/nginx…   22B                 
<missing>           13 days ago         /bin/sh -c set -x  && apt-get update  && apt…   53.8MB              
<missing>           13 days ago         /bin/sh -c #(nop)  ENV NJS_VERSION=1.15.5.0.…   0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  ENV NGINX_VERSION=1.15.5-…   0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  LABEL maintainer=NGINX Do…   0B                  
<missing>           13 days ago         /bin/sh -c #(nop)  CMD ["bash"]                 0B                  
<missing>           13 days ago         /bin/sh -c #(nop) ADD file:f8f26d117bc4a9289…   55.3MB


回答3:

You can do this by changing the ENTRYPOINT of the Dockerfile to run /bin/bash instead of the ENTRYPOINT / CMD.

this will make a new image that u can login and run the application on your own (nice for debugging in case the original image exits)

# comment the CMD/ENTRYPOINT
### ENTRYPOINT ["/opt/my_app.sh"]

# make a new CMD that simply starts /bin/bash
CMD ["/bin/bash"]

Then build the image:

$ docker build -t srvtemp .

And run:

$ docker exec -ti srvtemp /bin/bash

Alternatively, you can add --entrypoint /bin/bash to the docker exec command args

$ docker run -ti --name srvtemp --entrypoint /bin/bash