Can't edit docker images file in host - docker

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/.

Related

How to modifiy a file inside docker Image

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

Trying to run "comitted" Docker image, get "cannot mount volume over existing file, file exists"

I am developing a Docker image. I started with a base image and was working inside it interactively, using bash. I installed a bunch of stuff, and the install (which included compiling a lot of code) took over 20 minutes, so to save my work, I used:
$ docker commit 0f08ac958391 myproject:wip
Now when I try to run the image:
$ docker run --rm -it myproject:wip
docker: Error response from daemon: cannot mount volume over existing file, file exists /var/lib/docker/overlay2/95aa9a9ea7cc0b1ba302adbd287e4d7059ee4fbe64183404df3bc65df332ee63/merged/run/host-services/ssh-auth.sock.
What is going on? How do I fix this?
Note about related/duplicate questions: while there are other questions about this error message, none of the answers directly explain why the error happens in this situation or what to do about it. In fact, most of the questions have no answers at all.
When I ran the base image, I included a mount for the SSH agent socket:
$ docker run --rm -it -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock myproject:dev /bin/bash
This bind mounts a file from the host (actually the Docker daemon VM) to a file in the Docker container. When I committed the running image, the image contained the file /run/host-services/ssh-auth.sock. The image also contained an empty volume reference to /run/host-services/ssh-auth.sock. This means that when I ran
$ docker run --rm -it myproject:wip
It was equivalent to running
$ docker run -v /run/host-services/ssh-auth.sock --rm -it myproject:wip
Unfortunately, what that command does is create an anonymous volume and mount it into the directory /run/host-services/ssh-auth.sock in the container. This works if the container has such a directory or even if it does not. What causes it to fail is if the target name is taken up by a file. Docker will not mount a volume over a file.
The solution is to explicitly provide a mapping from a host file to the target volume. Any host file will do, but in my case it is best to use the original. So this works:
docker run --rm -it -v /run/host-services/ssh-auth.sock:/run/host-services/ssh-auth.sock myproject:wip

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

(dockerfile) for flag -v: bad mode specified

I have problems with the introduction of these instructions https://github.com/notabenoid/notabenoid-dockerfile
Out my error command
docker run -v `pwd`:/srv/example.com -p 127.0.0.1:8080:80 --name notabenoid notabenoid
I managed to turn the site, but my goal is to change a few files and pictures
How to edit files to container ?
use docker execto modify some files in a container, see the doc
https://docs.docker.com/engine/reference/commandline/exec/
check also the docs for docker run
https://docs.docker.com/engine/reference/commandline/run/
and the examples with -v
If You only need to change some files use docker cp.
docker run -p 127.0.0.1:8080:80 --name notabenoid notabenoid
docker cp notabenoid:/srv/example.com/file_to_change .
edit file
docker cp file_to_change notabenoid:/srv/example.com/file_to_change
where /srv/example.com/file_to_change is a path to file in container.
edit
Let's Your new logo is /home/Hellioob/new_logo.gif.
docker cp /home/Hellioob/new_logo.gif notabenoid:/notabenoid/site/www/i/logo.gif

Docker - how can I copy a file from an image to a host?

My question is related to this question on copying files from containers to hosts; I have a Dockerfile that fetches dependencies, compiles a build artifact from source, and runs an executable. I also want to copy the build artifact (in my case it's a .zip produced by sbt dist in '../target/`, but I think this question also applies to jars, binaries, etc.
docker cp works on containers, not images; do I need to start a container just to get a file out of it? In a script, I tried running /bin/bash in interactive mode in the background, copying the file out, and then killing the container, but this seems kludgey. Is there a better way?
On the other hand, I would like to avoid unpacking a .tar file after running docker save $IMAGENAME just to get one file out (but that seems like the simplest, if slowest, option right now).
I would use docker volumes, e.g.:
docker run -v hostdir:out $IMAGENAME /bin/cp/../blah.zip /out
but I'm running boot2docker in OSX and I don't know how to directly write to my mac host filesystem (read-write volumes are mounting inside my boot2docker VM, which means I can't easily share a script to extract blah.zip from an image with others. Thoughts?
To copy a file from an image, create a temporary container, copy the file from it and then delete it:
id=$(docker create image-name)
docker cp $id:path - > local-tar-file
docker rm -v $id
Unfortunately there doesn't seem to be a way to copy files directly from Docker images. You need to create a container first and then copy the file from the container.
However, if your image contains a cat command (and it will do in many cases), you can do it with a single command:
docker run --rm --entrypoint cat yourimage /path/to/file > path/to/destination
If your image doesn't contain cat, simply create a container and use the docker cp command as suggested in Igor's answer.
docker cp $(docker create --name tc registry.example.com/ansible-base:latest):/home/ansible/.ssh/id_rsa ./hacked_ssh_key && docker rm tc
wanted to supply a one line solution based on pure docker functionality (no bash needed)
edit: container does not even has to be run in this solution
edit2: thanks to #Jonathan Dumaine for --rm so the container will be removed after, i just never tried, because it sounded illogical to copy something from somewhere which has been already removed by the previous command, but i tried it and it works
edit3: due the comments we found out --rm is not working as expected, it does not remove the container because it never runs, so I added functionality to delete the created container afterwards(--name tc=temporary-container)
edit 4: this error appeared, seems like a bug in docker, because t is in a-z and this did not happen a few months before.
Error response from daemon: Invalid container name (t), only [a-zA-Z0-9][a-zA-Z0-9_.-] are allowed
A much faster option is to copy the file from running container to a mounted volume:
docker run -v $PWD:/opt/mount --rm --entrypoint cp image:version /data/libraries.tgz /opt/mount/libraries.tgz
real 0m0.446s
** VS **
docker run --rm --entrypoint cat image:version /data/libraries.tgz > libraries.tgz
real 0m9.014s
Parent comment already showed how to use cat. You could also use tar in a similar fashion:
docker run yourimage tar -c -C /my/directory subfolder | tar x
Another (short) answer to this problem:
docker run -v $PWD:/opt/mount --rm -ti image:version bash -c "cp /source/file /opt/mount/"
Update - as noted by #Elytscha Smith this only works if your image has bash built in
Not a direct answer to the question details, but in general, once you pulled an image, the image is stored on your system and so are all its files. Depending on the storage driver of the local Docker installation, these files can usually be found in /var/lib/docker/overlay2 (requires root access). overlay2 should be the most common storage driver nowadays, but the path may differ.
The layers associated with an image can be found using $ docker inspect image IMAGE_NAME:TAG, look for a GraphDriver attribute.
At least in my local environment, the following also works to quickly see all layers associated with an image:
docker inspect image IMAGE_NAME:TAG | jq ".[0].GraphDriver.Data"
In one of these diff directories, the wanted file can be found.
So in theory, there's no need to create a temporary container. Ofc this solution is pretty inconvenient.
First pull docker image using docker pull
docker pull <IMG>:<TAG>
Then, create a container using docker create command and store the container id is a variable
img_id=$(docker create <IMG>:<TAG>)
Now, run the docker cp command to copy folders and files from docker container to host
docker cp $img_id:/path/in/container /path/in/host
Once the files/folders are moved, delete the container using docker rm
docker rm -v $img_id
You essentially had the best solution already. Have the container copy out the files for you, and then remove itself when it's complete.
This will copy the files from /inside/container/ to your machine at /path/to/hostdir/.
docker run --rm -v /path/to/hostdir:/mnt/out "$IMAGENAME" /bin/cp -r /inside/container/ /mnt/out/
Update - here's a better version without the tar file:
$id = & docker create image-name
docker cp ${id}:path .
docker rm -v $id
Old answer
PowerShell variant of Igor Bukanov's answer:
$id = & docker create image-name
docker cp ${id}:path - > local-file.tar
docker rm -v $id
I am using boot2docker on MacOS. I can assure you that scripts based on "docker cp" are portable. Because any command is relayed inside boot2docker but then the binary stream is relayed back to the docker command line client running on your mac. So write operations from the docker client are executed inside the server and written back to the executing client instance!
I am sharing a backup script for docker volumes with any docker container I provide and my backup scripts are tested both on linux and MacOS with boot2docker. The backups can be easily exchanged between platforms. Basically I am executing the following command inside my script:
docker run --name=bckp_for_volume --rm --volumes-from jenkins_jenkins_1 -v /Users/github/jenkins/backups:/backup busybox tar cf /backup/JenkinsBackup-2015-07-09-14-26-15.tar /jenkins
Runs a new busybox container and mounts the volume of my jenkins container with the name jenkins_jenkins_1. The whole volume is written to the file backups/JenkinsBackup-2015-07-09-14-26-15.tar
I have already moved archives between the linux container and my mac container without any adjustments to the backup or restore script. If this is what you want you find the whole script an tutorial here: blacklabelops/jenkins
You could bind a local path on the host to a path on the container, and then cp the desired file(s) to that path at the end of your script.
$ docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
nginx:latest
Then there is no need to copy afterwards.

Resources