How to create new docker image based on existing image? - docker

I just started using docker. I create an image using docker file. How can I create a new image from that existing image?

Let's say you have a container bd91ca3ca3c8 running, and you want to create a new image after you made changes in the container. Generating another image will allow you to preserve your changes.
In that case you can run:
docker commit -p -a "author_here" -m "your_message" bd91ca3ca3c8 name_of_new_image
-p pauses the container while commit command is building the new image.
-a allows you to supply author information of the new image.
-m allows you to add a comment just as in the Git.

You can create a new image by using docker command $docker build -f docker_filename . , It will first read the Dockerfile where the instructions are written and automatically build the image. The instruction in the Dockerfile contains the necessary commands to assemble an image. Once, the image is build, it will be assigned an image id.
The image can be pushed to the docker registry hub. For this, the user must create an account in the docker registry hub.
An example of Dockerfile looks like this,
FROM docker/whalesay:latest
RUN apt-get -y update && apt-get install -y fortunes
CMD /usr/games/fortune -a | cowsay
Here, the first instruction tells the new image will be using docker/whalesay:latest image.
The second instruction will run the two commands.
And the third instruction tells that when the environment is set up "fortune -a" command should run.

In order to create a new image from an existing image all you have to do is to specify 'FROM' for e.g:
FROM sergiu/ubuntu
MAINTAINER sergiu

I am also new in docker but what i find might be helpful.
1) whenever you write "FROM" and run docker file, docker look in his repo and first load that image. so if you have any local image you want to use in "FROM", then it should be loaded.
2) what parameter you give in "FROM" is important, as if you give repo_name or tag wrong it give the error msg. so for this run "docker images" command to see your image correct repo_name and tag.
3) now you can start your new docker file like this
FROM REPOSITORY:TAG
and it will work

Docker commit: Creates a new image from a container’s changes.
It can be useful to commit a container’s file changes or settings into a new image. This allows you to debug a container by running an interactive shell, or to export a working dataset to another server. Generally, it is better to use Dockerfiles to manage your images in a documented and maintainable way.

You can follow the below command to create an image for an existing image:
docker tag jboss/wildfly myimage:v1
Creates an image called myimage with the tag v1 for the image jboss/wildfly:latest

Related

Make docker file from local image?

I have docker file which make image.
FROM public.ecr.aws/lambda/python:3.9
RUN export LANG=en_US.UTF-8
RUN export PYTHONUNBUFFERED=1
docker build -f dockers/mydocker -t python .
then I would like to make images from this image.
There are listed image named basic docker images
Then in another Dockerfile.
FROM python
ADD ./Pipfile* ./
RUN pipenv install --ignore-pipfile
When I try to build this dockerfile
There comes like this
FROM docker.io/library/python
Does this mean I can use local image to build next image?
I need to make local repository for this purpose ??
Or any other way to do this??
This is probably working fine, but you should be careful to pick names that don't conflict with standard Docker Hub image names.
A Docker image name has the form registry.example.com/path/name. If you don't explicitly specify a registry, it always defaults to docker.io (this can't be changed), and if you don't specify a path either, it defaults to docker.io/library/name. This is true in all contexts – the docker build -t option, the docker run image name, Dockerfile FROM lines, and anywhere else an image name appears.
That means that, when you run docker build -t python, you're creating a local image that has the same name as the Docker Hub python image. The docker build diagnostics are showing you the expanded name. It should actually be based on your local image, though; Docker won't contact a remote registry unless the image is missing locally or you explicitly tell it to.
I'd recommend choosing some unambiguous name here. You don't specifically need a Docker Hub account, but try to avoid bare names that will conflict with standard images.
# this will work even if you don't "own" this Docker Hub name
docker build -f Dockerfile.base -t whitebear/python .
FROM whitebear/python
...
(You may have some trouble seeing the effects of your base image since RUN export doesn't do anything; change those lines in the base image to ENV instead.)

Docker -- modify only FROM value while docker commit

Is it possible only to modify the FROM value while executing docker commit ?
Say my active container is of Ubuntu 16.04 and I wanted to create an image off it, but Ubuntu version should be of 18.04, rest remains the same.
Does Docker support this scenario ?
Expecting like : docker commit —change=FROM ubuntu:18.04
The answer is no. You can't modify the base image with docker commit --change=FROM command.
The FROM instruction is not supported for --change option.
Here is the excerpt from the docs:
The --change option will apply Dockerfile instructions to the image
that is created. Supported Dockerfile instructions:
CMD|ENTRYPOINT|ENV|EXPOSE|LABEL|ONBUILD|USER|VOLUME|WORKDIR
If you don't have dockerfile for your container then, I would suggest to use either:
docker history command to generate Dockerfile. As mentioned here.
OR
Use dfimage utiliyy as mentioned here.
And then change the FROM instruction in your new generated dockerfile.
This is a strong reason to never use docker commit.
If you have a commit-based workflow, you need to docker run a container from some base image, perform some steps, and commit the result. Once you've done this, though, Docker has no idea what happened in between; it just knows that there's an image, and some opaque set of filesystem changes, and it's being asked to create an image from that.
Say you're using an old version of Ubuntu, and you want to upgrade to something newer. In a commit-based workflow, it's up to you to do all of the steps by hand. To keep track of this, you might write down a text file of the steps you want to perform:
# `docker run` a container using this base image
FROM ubuntu:18.04
# `docker cp` this file into the image
COPY package.deb /
# Run this command in the container shell
RUN dpkg -i /package.deb
# After committing the image, `docker run` the new image with this command
CMD some_command
That specific format is exactly the Dockerfile format, though: you can check it into source control, run docker build, and get the image back. Your coworker can do that too even if they don't have the exact setup you do, and even if they don't type the commands exactly the same way. And when you do need to upgrade the base image, you can just change the first line to FROM ubuntu:20.04 and docker build it again.

what is the correct way to update a docker image

I created an ubuntu docker container, copied a mirror of a c++ library (sized 1.2 gb) I'll be using on it (on the docker container's home directory), built it on it and forgot to remove the mirror before creating the image and pushing to docker hub.
I then tried to re-run the container from the image to remove the c++ mirror so i can commit the new image , but the new image didn't downsize for a reason i ignore . After i run docker images i still have :
REPOSITORY TAG IMAGE ID CREATED SIZE
tawfik741/opencascade-build amd64 74f333aa7293 16 minutes ago 1.79GB
The commands i ran are :
Creating the container with :
docker run --name opencascade-build -it ubuntu:latest bash
Copying the C++ library mirror so i build it on the container :
docker cp opencascade-dev-mirror [my-container-id]:/home
After building my library i did :
sudo docker commit --author "Tawfik" --message "opencascade-build" [my-container-id] tawfik741/opencascade-build:amd64
and pushed it to a private repo with :
docker push tawfik741/opencascade-build:amd64
after figuring up that i forgot to remove that opencascade-dev-mirror from the container i decided to run the container , remove it , and save the new image , i tried in to save a new image but it's exactly the same size as the old one :
I ran the docker container from the image with :
docker run -it tawfik741/opencascade-build:amd64 /bin/bash
I updated the container then ran :
docker commit --author "Onboard SARL" --message "opencascade-build" [my-container's id] tawfik741/opencascade-build:correction-amd64-correction
but the tawfik741/opencascade-build:amd64-correction has the same size as the tawfik741/opencascade-build:amd64 image .
You cannot edit, modify, or update an image once you've created it.
You can create a new image based on an existing image. The way Docker works internally, the new image always contains the entire old image, plus a description of what changed from the old image. Doing this never makes the new image smaller, only larger.
You need to start over and create a new image starting from the original base image. If you use the standard docker build command and Dockerfile system, it should be enough to delete the COPY line that adds the large file to the image and rebuild. If you're using docker commit, you need to completely start over and hope you repeat the same manual commands in the same way; even if you're trying to "iterate rapidly" you'll be much better off switching to a Dockerfile.

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

Resources