How to create a Image from a Docker Container? - docker

As I want to make my existing application as a Docker images. And I have to install lot of installation which I can't do using Docker file. How I am doing is I created a Docker container with OS, and log-in in to that and I Installed all the software I needed. Now I want to make the image out of it.

You can use docker commit.
Check out Docker commit official documentation:
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
--author , -a Author (e.g., “John Hannibal Smith hannibal#a-team.com”)
--change , -c Apply Dockerfile instruction to the created image
--message , -m Commit message
--pause , -p true Pause container during commit
Note this important remark:
By default, the container being committed and its processes will be paused while the image is committed. This reduces the likelihood of encountering data corruption during the process of creating the commit.
However this is not the best practice. You should build everything using a dockerfile for maintainability.

docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
See the doc for more detailed explanation
Unless you have very specific need which prevents using Dockerfile to build your image, you should prefer the Dockerfile with the docker build command

Related

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.

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

how to ignore logs with docker commit

I use docker pull ubuntu to get the ubuntu:latest docker
Once I had deploy some artifacts in this container, and I want to use it to other place, then I used docker commit ${container_id}
However I found that when I use command of docker commit, it push all the files, including the application logs.
I've google for some cases, it may use docker file, and set the .dockerignore file to ignore those files I don't need.
But it matters that I've deployed the application with a license, so could I use this container with the only docker commit to commit the changes?
docker commit will always capture EVERYTHING in the container filesystem. It's just the way it works.
.dockerignore only applies to the docker build command. docker build uses a Dockerfile to take an existing image (like ubuntu:latest), run some modification on it, and commit the result.
If you want to build a container for use somewhere else, a Dockerfile is the way to approach it. You didn't provide much info, so here is a SUPER sparse example...
# Dockerfile
FROM ubuntu:latest
ADD myartifact /src
CMD /src/my_script.sh
and then...
docker build -t myOrg/myImage .
After which you can run the image with
docker run myOrg/myImage

Docker commit doesn't save changes

Yeah, you're right, they are many topics like that. I didn't find a solution for my problem. So give me a chance!
I run a docker container with no defined volumes. So what I want is to commit changes like:
docker commit 3a09b2588478 myfantasticimage
docker save myfantasticimage > /tmp/fantasticimagecommit.tar
Now I transfer the image via scp to another docker-host an do
docker load < /tmp/fantasticimagecommit.tar
Starting image and I can't see change I do before commited it.
What's the problem. According to the Dockerfile, no volumes are defined.
Thanks!
Update: I've found volumes via docker inspect-command
"VolumesRW": {
"/var/lib/": true,
"/var/log/": true,
"/var/www/": true
}
What could be a workaround? I want do back up every 6 hours a container, so I can restore it on the same or another machine without expended effort.
"docker commit" cannot save mount volumes' data ~
You should docker cp files to the container ~
For Saving and Loading Docker Images in another machine without going through docker hub
use below commands
Let say you have an app.tar file then for saving it with app and tag number. Use below commands
docker image save -o app.tar app:3
For Loading it use below command
docker image load -i app.tar

Docker rails app and git

Lets say I have a container that is fully equipped to serve a Rails app with Passenger and Apache, and I have a vhost that routes to /var/www/app/public in my container. Since a container is supposed to be sort of like a process, what would I do when my Rails code changes? If the app was cloned with Git, and there are pending changes in the repo, how can the container pull in these changes automatically?
You have a choice on how you want to structure your container, depending on your deployment philosophy:
Minimal: You install all your rails pre-reqs in the Docker file (RUN commands), but have the ENTRYPOINT be something like "git pull && bundle install --deployment && rails run". At container boot time it will get your latest code.
Snapshot: Same as above, but have the ENTRYPOINT also be a RUN command. This way, the container has a pre-installed snapshot of the code, but it will still update when the container is booted. Sometimes this can speed up boot time (i.e. if most of the gems are already installed).
Container as Deployment: Same as above, but change the ENTRYPOINT to be "rails run" only. This way, your container is your code. You'll have to make new containers every time you change rails (automation!). The advantage is that your container won't need to contact your code repo at all. The downside is that you have to always remember what the latest container is. (Tags can help) And right now, Docker doesn't have a good story on cleaning up old containers.
In this scenario, it sounds like you have built an image and are now running this image in a container.
Using the image your running container originates from, you could add another build step to git pull your most up to date code. I'd consider this an incremental update as your building upon a preexisting image. I'd recommend tagging and pushing to your (assuming your using a private index) appropriately. The new image would be available to run.
Depending on the need, you could also rebuild the base image of your software. I'm assuming your using a Dockerfile to build your original image which includes a git checkout of your software. You could then tag and push to your index for use appropriately.
In docker v0.8, It will be possible to start a new command in a running container, so you will be able to do what you want.
In the meantime, one solution would consist in using volumes.
Option 1: Docker managed volumes
FROM ubuntu
...
VOLUME ["/var/www/app/public"]
ADD host/src/path /var/www/app/public
CMD start rails
Start and run your container, then when you need to git pull, you can simply:
$ docker ps # -> retrieve the id of the running container
$ docker run -volumes-from <container id> <your image with git installed> sh -c 'cd/var/www/app/public && git pull -u'
This will result in your first running container to have the sources updated.
Option 2: Host volumes
You can start your container with:
$ docker run -v `pwd`/srcs:/var/www/app/public <yourimage>
and then simply git pull in your host's sources directory, it will update the container's sources.

Resources