Docker commit - does not keep new settings? - docker

I'm trying to create (without a dockerfile) a custom image (apache) which I want to publish to other programmers.
I already have this image :
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
eboraas/apache latest ddf3c3b74564 3 months ago 365MB
Now let's create a container with settings :
docker run -p 8520:80 -v //c/Users/sff/apache:/var/www/html -d eboraas/apache
OK , now all is working and I do see the test page :
BTW - docker ps -a is now :
C:\r>docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3a1083fded97 eboraas/apache "/usr/sbin/apache2ct…" 2 minutes ago Up 2 minutes 443/tcp, 0.0.0.0:8520->80/tcp eloquent_heisenberg
OK
I was told that I can use docker commit in order to keep the container as a custom new image.
And so I did :
C:\r>docker commit 3a1083fded97 131313222/shared-apache
sha256:14135d48fcf827527d655225908a29b15223317810be9cf22651ae375a87a774
And it did save new image :
C:\r>docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
131313222/shared-apache latest 14135d48fcf8 49 seconds ago 365MB
eboraas/apache latest ddf3c3b74564 3 months ago 365MB
But now I expect that running docker run 131313222/shared-apache - will keep(!!) the folder mapping and the port mapping :
But If I run this :
docker run 131313222/shared-apache
I get :
C:\r>docker run 131313222/shared-apache AH00558: apache2: Could not
reliably determine the server's fully qualified domain name, using
172.17.0.2. Set the 'ServerName' directive globally to suppress this message
And obviously the test page doesn't work.
Question:
Why doesn't the commit command ( into a new image) save the port and volume mapping ?
In other words : (without a docker file) - how can I create an image that will include its current settings ? I want developers to start working immediately as if each was writing :
docker run -p 8520:80 -v //c/Users/sff/apache:/var/www/html -d eboraas/apache
Shouldn't the commit do that already ?
I want everyone to see what I see without doing anything.

A Docker image only contains its filesystem and a small amount of metadata like the default command to run and environment variable settings. It doesn't contain any of the other settings you might specify, like port mappings, volume mounts, access to host devices, privileged access to host-level settings, or background mode. You simply can't create an image that defaults to the settings you show in the question.
If your audience is other programmers, I'd suggest writing up the sequence to build the image as a Dockerfile, and adding that Dockerfile and a shell script or Docker Compose YAML file that runs the image to a common source control repository.
In fact, I'd advise you to never use docker commit. The Dockerfile system is fairly straightforward (if you could specify these settings they'd be one line each in the Dockerfile; ENV foo bar replaces docker run -e foo=bar for example) and Dockerfiles can be checked into source control quite easily. When you need to rebuild your image – because a new version of Apache is out with a critical security update, because some of the software you bundled changed – a Dockerfile both gives you a record of what exactly you did to build the image, and a single command to actually do it.

Related

Name a docker at build and how to retrieve it

I tried to build a docker image. Then on docker images command, the list displays:
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> eaaf8e203bd4 1 min ago 253.2 MB
Is there a way in my Dockerfile to specify a name for this build? Or at docker build . command line?
Another question: I want to upload via SFTP the docker container on my production server and run it. Where are the containers stored?
You should use the -t option of docker build
docker build -t name:tag
The tag is optional.
I want to upload via SFTP the docker container on my production server and run it.
You should "upload" the image, and by that I mean push it to a docker registry running on your server.
You could also commit a running container into an intermediate image (which would freeze the running state of the container, but would not preserve the volume data, if one was declared in that container)
Then copy that archive, and docker import it.
See "How to move docker containers between different hosts".
Once imported, see "Where are docker images stored on the host machine?".
(/var/lib/docker/containers for containers)

Do docker containers retain file changes?

This is a very basic question, but I'm struggling a bit and would like to make sure I understand properly.
After a container is started from an image and some changes done to files within (i.e.: some data stored in the DB of a WebApp running on the container), what's the appropriate way to continue working with the same data between container stop and restart?
Is my understanding correct that once the container is stopped/finished (i.e.: exit after an interactive session), then that container is gone together with all file changes?
So if I want to keep some file changes I have to commit the state of the container into a new image / new version of the image?
Is my understanding correct that once the container is stopped/finished (i.e.: exit after an interactive session), then that container is gone together with all file changes?
No, a container persists after it exits, unless you started it using the --rm argument to docker run. Consider this:
$ docker run -it busybox sh
/ # date > example_file
/ # exit
Since we exited our shell, the container is no longer running:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
But if we had the -a option, we can see it:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
79aee3e2774e busybox:latest "sh" About a minute ago Exited (0) 54 seconds ago loving_fermat
And we can restart it and re-attach to it:
$ docker start 79aee3e2774e
$ docker attach 79aee3e2774e
<i press RETURN>
/ #
And the file we created earlier is still there:
/ # cat example_file
Wed Feb 18 01:51:38 UTC 2015
/ #
You can use the docker commit command to save the contents of the container into a new image, which you can then use to start new containers, or share with someone else, etc. Note, however, that if you find yourself regularly using docker commit you are probably doing yourself a disservice. In general, it is more manageable to consider containers to be read-only and generate new images using a Dockerfile and docker build.
Using this model, data is typically kept external to the container,
either through host volume mounts or using a data-only container.
You can see finished containers with docker ps -a
You can save a finished container, with the filesystem changes, into an image using docker commit container_name new_image_name
You can also extract data files from the finished container with: docker cp containerID:/path/to/find/files /path/to/put/copy
Note that you can also "plan ahead" and avoid trapping data you'll need permanently within a temporary container by having the container mount a directory from the host, e.g.
docker run -v /dir/on/host:/dir/on/container -it ubuntu:14.04

running incorrect docker image osx

I created a new image running:
docker build -t team1/es-image2 . | tee build.log
First, the create date doesn't reflect today's date. I wasn't concerned with that at first but after running it, it sort of makes sense...the running image is from another image created previously. I ran it with this command:
docker run -i -t --rm -P team1/es-image2
I verified that the correct image was running using:
docker ps
I deleted the older image and tried running again but it still appears to be running the older image because -P showed all the older mapped ports and the working directory was also from the older image.
So, I can't understand why, the build is using the older containers even though the Dockerfile is not specifying all the items that were specified in the older image.
Thanks!
docker ps
is only to show container.
To show images you need to use
docker images
And to delete them use
docker rmi
A little clarification about image and container.
An image is the definition of a container, and a container is a part of the system isolated from the current directory tree.
You use an image to run a container. You can use the same image to run multiple container.
When building the image from the Dockerfile, you may specify --no-cache=true to exclude any intermediate builds.

In Docker, what's the difference between a container and an image? [duplicate]

This question already has answers here:
What is the difference between a Docker image and a container?
(31 answers)
Closed 3 years ago.
What's the difference between a container and an image in Docker? In the Get started with Docker tutorial these terms are both used, but I do not understand the difference.
Can anybody please shed some light?
Images are frozen immutable snapshots of live containers. Containers are running (or stopped) instances of some image.
Start with the base image called 'ubuntu'. Let's run bash interactively within the ubuntu image and create a file. We'll use the -i and -t flags to give us an interactive bash shell.
$ docker run -i -t ubuntu /bin/bash
root#48cff2e9be75:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#48cff2e9be75:/# cat > foo
This is a really important file!!!!
root#48cff2e9be75:/# exit
Don't expect that file to stick around when you exit and restart the image. You're restarting from exactly the same defined state as you started in before, not where you left off.
$ docker run -i -t ubuntu /bin/bash
root#abf181be4379:/# ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root#abf181be4379:/# exit
But, the container, now no longer running, has state and can be saved (committed) to an image.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
abf181be4379 ubuntu:14.04 /bin/bash 17 seconds ago Exited (0) 12 seconds ago elegant_ardinghelli
48cff2e9be75 ubuntu:14.04 /bin/bash About a minute ago Exited (0) 50 seconds ago determined_pare
...
Let's create an image from container ID 48cff2e9be75 where we created our file:
$ docker commit 48cff2e9be75 ubuntu-foo
d0e4ae9a911d0243e95556e229c8e0873b623eeed4c7816268db090dfdd149c2
Now, we have a new image with our really important file:
$ docker run ubuntu-foo /bin/cat foo
This is a really important file!!!!
Try the command docker images. You should see your new image ubuntu-foo listed along with the ubuntu standard image we started with.
An image is an ordered collection of root filesystem changes and the corresponding execution parameters for use within a container runtime. Images are read-only.
https://docs.docker.com/glossary/?term=image
A container is an active (or inactive if exited) stateful instantiation of an image.
https://docs.docker.com/glossary/?term=container
Using an object-oriented programming analogy, the difference between a Docker image and a Docker container is the same as that of the difference between a class and an object. An object is the runtime instance of a class. Similarly, a container is the runtime instance of an image.
An object gets created only once when it is instantiated. Similarly, a container can be running or stopped. Containers are created out of an image, though this might not always be the case. The following example creates an Apache server image, runs the image, lists the images and then lists the containers:
Create a Dockerfile with the following contents:
FROM httpd:2.4
Install Apache server
sudo docker build -t my-apache2 .
Run the image
sudo docker run -it --rm --name my-running-app my-apache2
List Docker images
sudo docker images
List the running Docker containers
docker ps
List all containers
docker ps -a
List latest created containers
docker ps -l
An image is basically an immutable template for creating a container. It's easier to understand the difference between an image and container by considering what happens to an image to turn it into a container.
The Docker engine takes the image and adds a read-write filesystem on top, then initialises various settings. These settings include network options (IP, port, etc.), name, ID, and any resource limits (CPU, memory). If the Docker engine has been asked to run the container it will also initialise a process inside it. A container can be stopped and restarted, in which case it will retain all settings and filesystem changes (but will lose anything in memory and all processes will be restarted). For this reason a stopped or exited container is not the same as an image.
DockerFile --(Build)--> DockerImage --(run)--> DockerContainer
DockerFile is what you or developer write code to do something (ex- Install)
Docker Image is you get when you build docker file .
Docker Container is you get when you run your Docker image
We can get Docker Image from docker hub by pulling and then run it to get container .
Images [like vm]
Read only template used to create containers
Buuilt by you or other Docker users
Stored in the Docker Hub or your local Registry
Containers [like a runing machine]
Isolated application platform
Contains everything needed to run your application
Based on images
In Docker, it all begins with an image. An image is every file that makes up just enough of the operating system to do what you need to do. Traditionally you'd install a whole operating system with everything for each application you do. With Docker you pair it way down so that you have a little container with just enough of the operating system to do what you need to do, and you can have lots and lots of these efficiently on a computer.
Use docker images to see the installed images and docker ps to see the running images.
When you type docker run it takes the image, and makes it a living container with a running process. I tend to use:
docker run -ti <image>:<tag> bash
Lastly, images have their own set of ids and containers have their own set of ids - they don't overlap.
Containers are based on images. An image needs to be passed to the Dockers run command.
Example:
BusyBox image
http://i.stack.imgur.com/eK9dC.png
Here we specify an image called busybox. Docker does not have this image locally and pulls it from a public registry.
A registry is a catalog of Docker images that the Docker client can communicate with and download image from. Once the image is pulled, Docker starts a container and execute the echo hello world command.
Images: The filesystem and metadata needed to run containers. They can be thought of as an application packaging format that includes all of the dependencies to run the application, and default settings to execute that application. The metadata includes defaults for the command to run, environment variables, labels, and healthcheck command.
Containers: An instance of an isolated application. A container needs the image to define its initial state and uses the read-only filesystem from the image along with a container specific read-write filesystem. A running container is a wrapper around a running process, giving that process namespaces for things like filesystem, network, and PIDs.
When you execute a docker run command, you provide an image on the command line, along with any configurations, and docker returns a container based off of that image definition and configurations you provided.
References: to the docker engine, an image is just an image id. This is a unique immutable hash. A change to an image results in creating a new image id. However, you can have one or more references pointing to an image id, not unlike symbolic links. And these references can be updated to point to new image id's. Note that when you create a container, docker will resolve that reference at the time of container creation, so you cannot update the image of a running container. Instead, you create a new image, and create a new container based on that new image.
Layers: Digging a bit deeper, you have filesystem layers. Docker assembles images with a layered filesystem. Each layer is a read-only set of changes to the filesystem, and that layer is represented by a unique hash. Using these read-only layers, multiple images may extend another, and only the differences between those images need to be stored or transmitted over the network. When a Docker container is run, it receives a container specific read-write filesystem layer unique to that container, and all of the image layers are assembled with that using a union filesystem. A read is processed through each layer until the file is found, a deletion is found, or the file is not found in the bottom layer. A write performs a copy-on-write from the image read-only layer to the container specific read-write layer. And a deletion is recorded as a change to the container specific read-write layer. A common step in building images is to run a command in a temporary container based off the previous image filesystem state and save the resulting container specific layer as a layer in the new image.
Docker Images:
It contains a list of commands and instruction on how to build and run a container. So basically Images contains all the data and metadata required to fire up a container(also called blueprint).We can't lunch a container without specifying Images.
$docker images centos
List all the available version of centos.
Docker Container:
Containers are lunch from Images so we can say container is the running instance of an Images.
Container is a runtime construct, unlike Images which is build time construct.
The official difference is that the container is the last layer which is writable whereas the layers below are only readable and they belong to your image. The intuitive difference is that the docker instance is the instance virtualized by your docker daemon and the running your image, it operates within an isolated section of your kernel (this process is hidden from you). The image however is static, it doesn't run, it is just a pile of layers (static files). If we would relate this paradigm to object-oriented programming, the image is your class definition, whereas your docker instance is your class spawned object that resides in memory.
I have written a tutorial to reinforce your docker knowledge intuition:
http://javagoogleappspot.blogspot.com/2018/07/docker-basics.html
Image is the photo made from your phone.
Container is the phone.

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