Add a file in a docker image - docker

I've created a docker image of a project (very large project that takes time to compile) and I forgot to add a file in it.
I does not have to do with the build, it's just a test file.
Is it possible to add this file into my image without rebuilding everything ?
Thanks

Here's a full example to pull an image, add a local file to it, retag the image and push it back:
export IMAGE_URL=example.com/your_image:your_tag
docker pull $IMAGE_URL
docker create --name temp_container $IMAGE_URL
docker cp /host/path/to/file temp_container:/container/path/to/file
docker commit temp_container $IMAGE_URL
docker push $IMAGE_URL

Yes its possible, do the steps:
Mount the image and make a container
Do the command:
docker cp textFile.txt docker_container_name:/textFile.txt
Commit the container to build a new image with new tag version or another name;

Add the image using docker commit of a container as described above, or using Dockerfile.
Create a directory say temp and navigate into it
Move file file-to-be-added.extension to be added to the docker image into the newly created temp directory
Create a Dockerfile with below contents
Dockerfile
FROM your-registry/your-image:tag
COPY file-to-be-added.extension /destination/path/of/file-to-be-added.extension
Run below command to build the new image:
docker build -t your-registry/your-image:new-tag .
If required, push the image
docker push your-registry/your-image:new-tag

You should try to use docker commit.
Example: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
There's docker cp too, but it only works in running containers.
I hope this helps!
Brhaka

The ADD command is used to copy files/directories into a Docker image. It can copy data in three ways:
1. List item Copy files from the local storage to a destination in the Docker image.
2. Copy a tarball from the local storage and extract it automatically inside a destination in the Docker image.
3. Copy files from a URL to a destination inside the Docker image.
source: https://www.educative.io/edpresso/what-is-the-docker-add-command

Related

Recreate Docker image

I have to take a Docker image from a vendor site and then push the image into the private repository (Artifactory). This way the CI/CD pipeline can retrieve the image from the private repository and deploy the image.
What is the best way to achieve it, do I need to recreate the image?
steps:
take a pull of the base docker image from vendor.
create new folder for your new docker image.
create a Dockerfile.
write your base docker image.
do the changes inside this folder.
build new docker image using cmd.
push the image into docker hub.
refer this (not exactly according to your need, but this helps): https://www.howtoforge.com/tutorial/how-to-create-docker-images-with-dockerfile/
for cmd and Dockerfile changes, refer docker office doc site
I believe its a tar or zip file that they have given you by docker save and docker export.
You can perform below operations.
1. Perform docker load < file.tar - You will get the image name that's loaded. Note down the name.
1. Download the tar or zip file to your local.
2. Perform cat file.tar | docker import image_name_that_you_noted_above
3. You are good to use the image now. tag it to your repo and push, or directly run using docker run

Updating a docker image without the original Dockerfile

I am working on Flask app running on ec2 server inside a docker image.
The old dev seems to have removed the original Dockerfile, and I can't seem to find any instructions on a way to push my changes into to the docker image with out the original.
I can copy my changes manually using:
docker cp newChanges.py doc:/root/doc/server_python/
but I can't seem to find a way to restart flask. I know this is not the ideal solution but it's the only idea I have.
There is one way to add newChanges.py to existing image and commit that image with a new tag so you will have a fall back option if you face any issue.
Suppose you run alpine official image and you don't have DockerFile
Everytime you restart the image you will not have your newChanges.py
docker run --rm -name alpine alpine
Use ls inside the image to see a list of existing files that are created in Dockerfile.
docker cp newChanges.py alpine:/
Run ls and verify your file was copied over
Next Step
To commit these changes to your running container do the following:
Docker ps
Get the container ID and run:
docker commit 4efdd58eea8a updated_alpine_image
Now run your alpine image and you will the see the updated changes as suppose
docker run -it updated_alpine_image
This is what you will see in your update_alpine_image with having DockerFile
This is how you can rebuild the image from existing image. You can also try #uncletall answer as well.
If you just want to restart after docker cp, you can just docker stop $your_container, then docker start $your_container.
If you want to update newChanges.py to docker image without original Dockerfile, you can use docker export -o $your_tar_name.tar $your_container, then docker import $your_tar_name.tar $your_new_image:tag. Later, always reserve the tar to backup server for future use.
If you want continue to develop later use a Dockerfile in the future for further changes:
you can use docker commit to generate a new image, and use docker push to push it to dockerhub with the name something like my_docker_id/my_image_name:v1.0
Your new Dockerfile:
FROM my_docker_id/my_image_name:v1.0
# your new thing here
ADD another_new_change.py /root/
# others
You can try to examine the history of the image, from there you can probably re-create the Dockerfile. Try using docker history --no-trunc image-name
See this answer for more details

Questions on Docker Build and Local Docker Repo

I am trying to create a docker image using the below command .
docker build -t mytestapp .
My DockerFile looks like this
# Set the base image
FROM rhel7:latest
USER root
# Dockerfile author / maintainer
MAINTAINER Name <email.id#example.com>
# Update application repository list and install the Redis server.
RUN mkdir /usr/local/myapp/
ADD myapp-0.0.1-jar /usr/local/myapp/
RUN java -Dspring.profiles.active=qa -jar /usr/local/myapp/myapp-0.0.1.jar
# Expose default port
EXPOSE 8080
Questions:
1) Is it fine the way I am adding the JAR file. Will it be available inside /usr/local on the container after I prepared am image from the above build.
2) When I build the image using docker build command , is the build image is pushed to docker repository hub by default.
Since the WAR file contains credentials, I don't want to push the image to Docker Hub but we would like to push to our local Docker registry using Docker distribution and pushing with docker push.
Please clarify.
Answering your questions:
Docker recommends using the COPY instructions for adding single files into an image. It will be available inside the container at /usr/local/myapp/myapp-0.0.1-jar
When you build the image it will be available on your local docker-host. It won't leave the server unless you explicitly tell it so.
Another tip I want to give you is the recommended docker image naming convention, which is [Repository/Author]/[Imagename]:[Version].
So for your image it might be called zama/mytestapp:1.0
If you want to push it into your local registry, you'll have to name your image after the syntax [LocalRegistry:Port]/[Repository/Author]/[Imagename]:[Version].
So your image might now be called registry.example.com:5000/zama/mystestapp:1.0
If you have authentication on your registry, you need to docker login first and then simply push the image with docker push registry.example.com:5000/zama/mystestapp:1.0.

Docker: does pulling an image from DockerHub download a Dockerfile to localhost?

I would like to be able to pull a docker image from dockerhub and edit the dockerfile.. I am wondering if dockerhub actually downloads the dockerfile to the localhost and to where it is stored (I am running it from a MAC).
You dont download the docker image and edit their Dockerfile. The Dockerfile is an instruction set on how to build an image. Once the image is made, theres no going backwards. However if its on Dockerhub there should be a link to the Dockerfile. Look around at the page for links to the Dockerfile. Probably just a link to Github.
Once you have the dockerfile you then build it. For instance if you have a terminal open in the same folder as a Dockerimage file you could run
docker build -t myimage .
where myimage is the tag of your image. You will then have an instance of myimage on your local machine.
Also you can make a docker file that extends theres using FROM. For instance your docker file might start with
FROM java:6b38-jdk
# append to their image.
An image does not include a complete Dockerfile. When pulling an image you get an image manifest along with the required file system layers.
You can see some of the build steps with docker history --no-trunc IMAGE but it's not the complete Dockerfile.
There are utilities that try and generate a Dockerfile from the image history

Converting a mounted volume to a Docker Image

Eg:
I have a running container,with a volume mounted on it.
I want to convert the whole container along with the volume contents to a docker image.
I am tried using
docker commit container-name
docker push repo/imagename:tag
but it only pushed the container, no data from volume was preserved.
Is there any way to convert data on mounted docker volume to a docker image?
Use the following steps:
Use docker cp to copy the contents of the mount point to the docker host.
Create a new container using the same image.
Use docker cp to copy the content into the new container at desired location.
Commit the new container with content in it and push it to your repository.
Another way to do this is to create a DockerFile, then use From directive pointing to desired base image, and use COPY directive to copy the content to desired location (from dockerhost to image) at docker build time.
Neither export or commit will preserve your volume data. you have 2 options though.
First: covert it to image using commit or export it then move volumes manually
Second: copy the content of your volume to any location on your container then commit it and you have now all of the data inside your image. then after transferring. Move the volume data back to its original location for ex:-
cp /my-volume-dir /my-backup-dir
then after you transfer the image
mv /my-backup-dir /my-volume-dir

Resources