Hy i build a little image for docker on top of the debian:jessie image form the Docer Hub.
First i got debian:jessie from Docker Hub:
docker pull debian:jessie
Then I startet this image with a bash:
docker run -it debian:jessie
Then I installed my stuff e.g. ssh server and configured it.
Next from a second shell, i commitet the changes:
docker commit <running container id> debian-sshd
Now i have two images:
debian:jessie and debian-sshd
If i now want to delete debian:jessie, docker tells me i can't delete this because it has child-images(debian-sshd)
Is There a way I can make debian-sshd an independent image?
Most Dockerfiles start from a parent image. If you need to completely
control the contents of your image, you might need to create a base
image instead. Here’s the difference:
A parent image is the image that your image is based on. It refers to the contents of the FROM directive in the Dockerfile. Each
subsequent declaration in the Dockerfile modifies this parent image.
Most Dockerfiles start from a parent image, rather than a base image.
However, the terms are sometimes used interchangeably.
A base image either has no FROM line in its Dockerfile, or has FROM scratch.
Having quoted from docs, I would say that images are made up of layers, and since you have based your image on debian:jessie, one of the layers of debian-sshd is the debian:jessie image. If you want your independent image, build from scratch.
Other then that, all docker images are open source, so you can browse the dockerfile and modify it to suit your needs. Also, you could build from scratch if you want your own base image.
Related
I am confused with some terms.
Is Dockerile designed to create an image or a set of instruction of how to create a container from an image?
Because there are command e.g. FROM (to get the base image), RUN (To run executable in the container) etc. These command looks like an instruction to how to create the container.
Docker images are static, and are built from the instructions specified in the Dockerfile. They use Union File-System (UnionFS), so that the changes made when building an image are stacked on top of each other, generating a DAG (Directed Acyclic Graph) of build history. The FROM directive at the top of the Dockerfile simply points to an existing image, and starts building on top of that.
A container is simply an instantiated version of an image, basically just this UnionFS with a read/write layer dropped on top of it.
Interestingly, if you watch the output when you run docker build (in a directory with a Dockerfile) you'll see that what is happening is each instruction starts up a container based on the current state of the image, runs the command (apt-get install ... or whatever) and then commits that change to the image. That's why it's good to batch up commands in a Dockerfile - because each one will start a new container.
Dockerfile is used to create an image which you can later use to create a container using docker build.
From the docs
Docker can build images automatically by reading the instructions from a Dockerfile. A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image. Using docker build users can create an automated build that executes several command-line instructions in succession.
Also RUN will instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile and not "Run (To run executable in the container)". For details see this.
Image:
Docker engine use Dockerfile reference to build up Image from Dockerfile instruction like (FROM, RUN etc.)
Container:
Docker engine start container from Image and we can say Container is RUN time instance of Image
I am starting with the docker and its concepts. I have read official Guide on how to create images, and managed to create several images (proud).
Now I actually wanted to build an MySQL server, so I can connect it with my application. For that purpose, I have found official MySQL Dockerfile.
The thing is, when I run it with:
docker build -t mysql .
It creates two images:
First one has debian as Repository and stretch-slim as a TAG. Size is 55MB
Second has none for both. Size is 65MB.
I am now confused. Why two images? My understanding was it will be one image with Debian and MySQL, but not two.
Some guideline are appreciated.
This is the expected behavior:
As you can read in the first line of the docker-library-bot file from MySQL Dockerfile is says:
FROM debian:stretch-slim
As per Docker documentation:
A Dockerfile must start with a FROM instruction. The FROM
instruction specifies the Base Image from which you are building.
A base image is an image that has no parent.
So, as a result you will have two images:
debian -> Base Image
mysql -> Image created from the Base Image with mysql and all the software needed to run it.
If your Dockerfile has a FROM image, it has a dependency on another image, so It will download and generate all the dependant images.
If you need to create a BASE IMAGE you can do it by using a special image called scratch as a parent image.
i.e:
FROM scratch
ADD hello /
CMD ["/hello"]
For more information about how to create a base image:
https://docs.docker.com/develop/develop-images/baseimages/#create-a-simple-parent-image-using-scratch
What happens on docker registry server space side when an image is created from same docker file. So, for example in case below, if I push an image with tag 1.0 and then create another image with same docker file and push that with tag 1.1. Is it going to take any additional space on docker registry?
docker build . -t myRegistry.com/myImage:1.0
docker push myRegistry.com/myImage:1.0
docker build . -t myRegistry.com/myImage:1.1
docker push myRegistry.com/myImage:1.1
docker build . -t myRegistry.com/myImage:1.2
docker push myRegistry.com/myImage:1.2
docker build . -t myRegistry.com/myImage:1.3
docker push myRegistry.com/myImage:1.3
In your sample case, the container registry will use the same image, which is calculated by the image's sha256 value (also known as the IMAGE ID) -- the tag is simply alias to that unique image.
It's a one-to-many relationship, i.e., you can have many tags point to the same image. You can use docker images --no-trunc to see the full value of the IMAGE ID. (Note this is useful if you have consistency issues using common tags like "latest" or "develop" since you can't be sure which image it actually is unless you use the sha256 value.)
For builds on different machines/environments, using the same Dockerfile with the same files may result in the same hash, but it depends on many variables like how dynamic your dependencies are, if timestamps have changed, etc.
As #Henry mentioned, this further applies (largely behind the scenes) to individual layers of an image:
Docker images have intermediate layers that increase reusability,
decrease disk usage, and speed up docker build by allowing each step
to be cached. These intermediate layers are not shown by default.
see docs
Btw, to see a container's sha256 value to see which image it came from, you can inspect it, e.g., docker inspect --format='{{index .RepoDigests 0}}' mongo:3.4-jessie
If I want to build a docker image,
I need to base on a docker base image.
All the example I found are based on top of official images.
Can I base my image on other docker user images ?
The FROM line in your Dockerfile can point to any image. It may be an upstream image from the Docker hub, one on any other registry server including one you self host, or it may be another image you've built locally on your own docker build host. Lastly, it may be FROM scratch which starts without any base image, and is used by other base images at some point in their history.
Docker images create with multiple layers, I want to convert this to single layer is there any docker build command to achive this ? i googled for but cant find anything
No command to achieve that, and a single layer image is against docker's design concept. This Understand images, containers, and storage drivers doc described why docker image has multiple layers. In short, image layers are one of the reasons Docker is so lightweight. When you change a Docker image, such as when you update an application to a new version, a new layer is built and replaces only the layer it updates. Besides, even your image has only one layer, when you create a container with that image, docker still will add a thin Read/Writable container layer on the top of your image layer.
If you just want to move your image around and think one single layer could make it easier, you probably should try to use docker save command to create a tar file of it.
Or you have more complicated requirements, you may need to use VM image rather than docker image.
I have just workaround by using multistage build (the last build will be just a COPY from the previous build)
FROM alpine as build1
RUN echo "The 1st Build"
FROM scratch
COPY --from=build1 / /
First option:
# docker image build .
# docker run <your-image>
# docker container export <container-id created from previous command> -o myimage.tar.gz
# docker image import myimage.tar.gz
The imported image will be a single layer file system image.
Second option: (not a complete solution) - use multi stage builds to reduce number of image layers.
During build we can also pass --squash option to make it a single layer image.
Experimental (daemon)API 1.25+
Squash newly built layers into a single new layer
https://docs.docker.com/engine/reference/commandline/image_build/
Flattening a Docker Image to a Single Layer:
docker run -d --name flat_container nginx
docker export flat_container > flat.tar
cat flat.tar | docker import - flat:latest
docker image history flat