How to modifiy a file inside docker Image - docker

I pulled a docker image from https://github.com/snowflakedb/SnowAlert.
But after pulling the Image, I don't see any containers running. I used
docker container ls command and it returned no containers.
Now due to some usecase I want to modify a file inside this docker image.
What is the correct way to do it?
Thanks

Here is what resolved my issue.
After pulling the repository from the github I ran below commands
sudo docker images
This will display the names of existing images. Now copy the Image name in which you need to do the modification.
sudo docker run -it <copied_image_name> bash
This will open a bash where all the files are residing. Do the modification where ever it is required then type exit
Copy the container Id from below command
sudo docker ps -a
Now we need to commit the changes into new Image using below command
sudo docker commit <container_id> <new_image_name>
Thats all
Now do sudo docker images this will display the newly created image with the modified content.
Thanks

Don't confuse image with container: https://phoenixnap.com/kb/docker-image-vs-container.
You need to "up" image to create appropriate container for it: https://docs.docker.com/get-started/part2/#run-your-image-as-a-container
If you want to inspect/edit any container use command (it like ssh to container's server):
docker exec -it CONTAINER_ID bash
To get all docker containers and find their IDs use command:
docker ps -a

Related

How to print the current directory of the docker image which is running in a centOS7 OS from windows docker desktop [duplicate]

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.
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
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
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.
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
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.
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.
you can use dive to view the image content interactively with TUI
https://github.com/wagoodman/dive
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
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
In my case no shell was supported in container except sh. So, this worked like a charm
docker exec -it <container-name> sh
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.
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.
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.
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)
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
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.
This will launch a bash session for the image:
docker run --rm -it --entrypoint=/bin/bash
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
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.
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.
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
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.
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
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.
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.
My preferred way to understand what is going on inside container is:
expose -p 8000
docker run -it -p 8000:8000 image
Start server inside it
python -m SimpleHTTPServer
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
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.
3) Accessing in bash to the running container filesystem with a specific working directory :
docker exec -it -w /var/lib containerId bash
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" ]
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
inside the container install mc and ssh: docker exec -it <container> /bin/bash, then with prompt install mc and ssh packages
in same exec-bash console, run mc
press ESC then 9 then ENTER to open menu and select "Shell link..."
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
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
I had an unknown container, that was doing some production workload and did not want to run any command.
So, I used docker diff.
This will list all files that the container had changed and therefore good suited to explore the container file system.
To get only a folder you can just use grep:
docker diff <container> | grep /var/log
It will not show files from the docker image. Depending on your use case this can help or not.
Late to the party, but in 2022 we have VS Code

Docker image will not launch

Trying to launch a Docker image but it will not launch the process
The command is as follows:
sudo docker run --security-opt seccomp=unconfined blackarchlinux/blackarch
no error message is returned.
I would do the following things
see if my container is running or it is created
$ docker ps or docker ps -a
see if my image is pulled ?
$ docker images
if container is created but not running then I could also check the logs
$ docker logs my-container-name
if you can add in more details, probably would be able to investigate more
You want to start a shell up inside the container and use the tools in there, I assume.
In that case you need to add the -it options and tell docker which program/shell you want to run. Something like
sudo docker run -it --security-opt seccomp=unconfined blackarchlinux/blackarch /bin/bash

Explore content of files of nginx container on my host machine [duplicate]

I did a docker pull and can list the image that's downloaded. I want to see the contents of this image. Did a search on the net but no straight answer.
If the image contains a shell, you can run an interactive shell container using that image and explore whatever content that image has. If sh is not available, the busybox ash shell might be.
For instance:
docker run -it image_name sh
Or following for images with an entrypoint
docker run -it --entrypoint sh image_name
Or if you want to see how the image was built, meaning the steps in its Dockerfile, you can:
docker image history --no-trunc image_name > image_history
The steps will be logged into the image_history file.
You should not start a container just to see the image contents. For instance, you might want to look for malicious content, not run it. Use "create" instead of "run";
docker create --name="tmp_$$" image:tag
docker export tmp_$$ | tar t
docker rm tmp_$$
The accepted answer here is problematic, because there is no guarantee that an image will have any sort of interactive shell. For example, the drone/drone image contains on a single command /drone, and it has an ENTRYPOINT as well, so this will fail:
$ docker run -it drone/drone sh
FATA[0000] DRONE_HOST is not properly configured
And this will fail:
$ docker run --rm -it --entrypoint sh drone/drone
docker: Error response from daemon: oci runtime error: container_linux.go:247: starting container process caused "exec: \"sh\": executable file not found in $PATH".
This is not an uncommon configuration; many minimal images contain only the binaries necessary to support the target service. Fortunately, there are mechanisms for exploring an image filesystem that do not depend on the contents of the image. The easiest is probably the docker export command, which will export a container filesystem as a tar archive. So, start a container (it does not matter if it fails or not):
$ docker run -it drone/drone sh
FATA[0000] DRONE_HOST is not properly configured
Then use docker export to export the filesystem to tar:
$ docker export $(docker ps -lq) | tar tf -
The docker ps -lq there means "give me the id of the most recent docker container". You could replace that with an explicit container name or id.
docker save nginx > nginx.tar
tar -xvf nginx.tar
Following files are present:
manifest.json – Describes filesystem layers and name of json file that has the Container properties.
.json – Container properties
– Each “layerid” directory contains json file describing layer property and filesystem associated with that layer. Docker stores Container images as layers to optimize storage space by reusing layers across images.
https://sreeninet.wordpress.com/2016/06/11/looking-inside-container-images/
OR
you can use dive to view the image content interactively with TUI
https://github.com/wagoodman/dive
EXPLORING DOCKER IMAGE!
Figure out what kind of shell is in there bash or sh...
Inspect the image first: docker inspect name-of-container-or-image
Look for entrypoint or cmd in the JSON return.
Then do: docker run --rm -it --entrypoint=/bin/bash name-of-image
once inside do: ls -lsa or any other shell command like: cd ..
The -it stands for interactive... and TTY. The --rm stands for remove container after run.
If there are no common tools like ls or bash present and you have access to the Dockerfile simple add the common tool as a layer.
example (alpine Linux):
RUN apk add --no-cache bash
And when you don't have access to the Dockerfile then just copy/extract the files from a newly created container and look through them:
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
To list the detailed content of an image you have to run docker run --rm image/name ls -alR where --rm means remove as soon as exits form a container.
If you want to list the files in an image without starting a container :
docker create --name listfiles <image name>
docker export listfiles | tar -t
docker rm listfiles
We can try a simpler one as follows:
docker image inspect image_id
This worked in Docker version:
DockerVersion": "18.05.0-ce"
if you want to check the image contents without running it you can do this:
$ sudo bash
...
$ cd /var/lib/docker # default path in most installations
$ find . -iname a_file_inside_the_image.ext
... (will find the base path here)
This works fine with the current default BTRFS storage driver.
Oneliner, no docker run (based on responses above)
IMAGE=your_image docker create --name filelist $IMAGE command && docker export filelist | tar tf - | tree --fromfile . && docker rm filelist
Same, but report tree structure to result.txt
IMAGE=your_image docker create --name filelist $IMAGE command && docker export filelist | tar tf - | tree --noreport --fromfile . | tee result.txt && docker rm filelist
I tried this tool - https://github.com/wagoodman/dive
I found it quite helpful to explore the content of the docker image.
Perhaps this is nota very straight forward approach but this one worked for me.
I had an ECR Repo (Amazon Container Service Repository) whose code i wanted to see.
First we need to save the repo you want to access as a tar file. In my case the command went like - docker save .dkr.ecr.us-east-1.amazonaws.com/<name_of_repo>:image-tag > saved-repo.tar
UNTAR the file using the command - tar -xvf saved-repo.tar. You could see many folders and files
Now try to find the file which contain the code you are looking for (if you know some part of the code)
Command for searching the file - grep -iRl "string you want to search" ./
This will make you reach the file. It can happen that even that file is tarred, so untar it using the command mentioned in step 2.
If you dont know the code you are searching for, you will need to go through all the files that you got after step 2 and this can be bit tiring.
All the Best !
There is a free open source tool called Anchore-CLI that you can use to scan container images. This command will allow you to list all files in a container image
anchore-cli image content myrepo/app:latest files
https://anchore.com/opensource/
EDIT: not available from anchore.com anymore, It's a python program you can install from https://github.com/anchore/anchore-cli
With Docker EE for Windows (17.06.2-ee-6 on Hyper-V Server 2016) all contents of Windows Containers can be examined at C:\ProgramData\docker\windowsfilter\ path of the host OS.
No special mounting needed.
Folder prefix can be found by container id from docker ps -a output.

How to list the files inside ubuntu:16.04 docker container?

I have created docker container for ubuntu:16.04 and spark.
my docker image name TestDocker
using spark application I have copied test.txt to container /opt/ml/ location.
when i am executing below command it is showing like below:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
xx.com/decision-trees-sample latest af30271f1528 19 minutes ago 959MB
then i try to execute below command
docker exec -it decision-trees-sample ls /opt/ml
it is showing error.
now I want to check file is copied or not using docker command,is it possible to check?
how can I list(LS) files contain in /opt/ml/ ?
you can launch a shell inside the container with the
docker exec
command, see the doc
https://docs.docker.com/engine/reference/commandline/exec/
For example, if the id of your container is 123abcdef, you may do either
docker exec -it 123abcdef ls /opt/ml
or open a shell inside your container
docker exec -it 123abcdef bash
and then launch ls or find or any other command
Try below steps
docker exec -it decision-trees-sample
then set the environmental variable as
export TERM=xterm
then try with
docker exec -it 123abcdef ls /opt/ml
basically it tell your which kind of terminal you are trying to open.It mainly due to some package not installed regarding terminals, you can also add it to ~/.bashrc file and commit the image.
I agree with above answers and docker exec is only for running containers but If you really want to explore container image content I would recommend using container-diff
container-diff analyze --type=file <IMG> | grep /opt/ml

Can't edit docker images file in host

I am new to docker and I have pulled docker image PredictionIO, I need to edit a file in it and re-run but I can't. docker image is not in my directories, too. how can I save the image to my host and edit it?
I use Ubuntu 17.04
thank you :)
There are 3 approaches to your problem:
Get the Dockerfile and edit it, then build the image yourself.
Run a container from the pulled image.
Then docker exec -it into it and do your modifications.
After that use docker commit <container id> repository/imagename:tag.
Use bind mounts to map the file to a host directory and edit the file, this way you dont even need to modify the image.
In order to do this, you need to specify the mount when creating the container:
mkdir /path/to/host/config/folder
create the required file(s) and then create the container:
docker run -d --name mycontainer -v /path/to/host/config/folder:/path/to/container/config/folder/ <repository>/<image>:<tag> <command>
Please note the -v switch. After this when you exec into container and navigate to /path/to/container/config/folder/ you will see the contents of the /path/to/container/config/folder/.

Resources