Docker creates two images - docker

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

Related

ubuntu-core as container os in base image

I'm currently reviewing possible solutions for container operation systems for our applications. I'm considering RancherOS and Ubuntu-Core. But since we are using docker base images, I'm a little confused how to create a docker base image with ubuntu-core. I can't find an official release candidate from canonical and I don't want to create it myself from a tag. How could I compose the base image?
I can't find an official release candidate from canonical
Yes, there is no officaial image on dockerhub, but this & some other high pull images are good to use I think.
How could I compose the base image
If you still do not want to use the images on docker hub. Then in fact you still can form your own docker image based on official ubuntu-core release like next:
Download Ubuntu Core based on 14.04 version
wget http://cdimage.ubuntu.com/ubuntu-core/trusty/daily/current/trusty-core-ppc64el.tar.gz
Import the files into docker
# cat trusty-core-ppc64el.tar.gz | docker import - ubuntucore
3ad6c6616b921b10a414238a226fb39eef85d8249ac7d767e84e275aaf90ab65
Guarantee that the image was created:
# docker images
Assure that your image is running fine:
# docker run ubuntucore ls
Detail refers to IBM guide, and, if you need to use the new version, you also can find it in http://cdimage.ubuntu.com/ubuntu-core

DockerFile: Is it use to create an image or To the docker host how to create the container

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

Docker create independent image

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.

What are the different ways of implementing Docker FROM?

Inheritance of an image is normally done using docker's from command, for example.
from centos7:centos7
In my case, I have a Dockerfile which I want to use as a base image builder, and I have two sub dockerfiles which customize that file.
I do not want to commit the original dockerfile as a container to dockerhub, so for example, I would like to do:
Dockerfile
slave/Dockerfile
master/Dockerfile
Where slave/Dockerfile looks something like this:
from ../Dockerfile
Is this (or anything similar) possible ? Or do I have to actually convert the top level Dockerfile to a container, and commit it as a dockerhub image, before I can leverage it using the docker FROM directive.
You don't have to push your images to dockerhub to be able to use them as base images. But you need to build them locally so that they are stored in your local docker repository. You can not use an image as a base image based on a relative path such as ../Dockerfile- you must base your own images on other image files that exists in your local repository.
Let's say that your base image uses the following (in the Dockerfile):
FROM centos7:centos7
// More stuff...
And when you build it you use the following:
docker build -t my/base .
What happens here is that the image centos7:centos7 is downloaded from dockerhub. Then your image my/base is built and stored (without versioning) in your local repository. You can also provide versioning to your docker container by simply providing version information like this:
docker build -t my/base:2.0 .
When an image has been built as in the example above it can then be used as a FROM-image to build other sub-images, at least on the same machine (the same local repository). So, in your sub-image you can use the following:
FROM my/base
Basically you don't have to push anything anywhere. All images lives locally on your machine. However, if you attempt to build your sub-image without a previously built base image you get an error.
For more information about building and tagging, check out the docs:
docker build
docker tag
create your own image

Why do you need a base image with Docker?

I have went through every single page of the documentation of Docker.
I do not understand, yet still, why a "base image" (for example, the Ubuntu Base Image) is necessary to furnish the containers before installing/creating an application environment.
My questions:
What is a base image and why is it required?
Why is it not possible to just to create a container and put the application in it similar to virtualenv of Python?
In fact, Docker works through application of layers that are added to the base image. As you have to maintain coherence between all these layers, you cannot base your first image on a moving target (i.e. your writable file-system). So, you need a read-only image that will stay forever the same.
Here is an excerpt of the documentation of Docker about the images:
Since Docker uses a Union File System, the processes think the whole file system is mounted read-write. But all the changes go to the top-most writable layer, and underneath, the original file in the read-only image is unchanged. Since images don’t change, images do not have state.
An image is just a snapshot of file system and dependencies or a specific set of directories of a particular application/software. By snapshot I mean, a copy of just those files which are required to run that piece of software (for example mysql, redis etc.) with basic configurations in a container environment. When you create a container using an image, a small section of resources from your system are isolated with the help of namespacing and cgroups, and then the files inside the image are copied in this isolated environment of resources.
Let us understand what is a base image:
A base image is a starting point or an initial step for the image that we finally want to create.
Suppose you want an image that runs redis (this is a silly example and you can achieve it another way, but just for the sake of explanation think you will not find that image on docker hub) You would need a starting point to create the image for that. So let us take Alpine image as a base image.
Alpine is the lightest image that contains files just to run basic commands(for example: ls, cd, apk add inside the container).
Create a Dockerfile with following commands:
FROM alpine
RUN apk add --update redis
CMD ["redis-server"]
Now when you run docker build . command, it gives the following output:
Sending build context to Docker daemon 2.048kB
Step 1/3 : FROM alpine
---> a24bb4013296
Step 2/3 : RUN apk add --update redis
---> Running in 535bfd2d1ff1
fetch http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/APKINDEX.tar.gz
fetch http://dl-
cdn.alpinelinux.org/alpine/v3.12/community/x86_64/APKINDEX.tar.gz
(1/1) Installing redis (5.0.9-r0)
Executing redis-5.0.9-r0.pre-install
Executing redis-5.0.9-r0.post-install
Executing busybox-1.31.1-r16.trigger
OK: 7 MiB in 15 packages
Removing intermediate container 535bfd2d1ff1
---> 4c288890433b
Step 3/3 : CMD ["redis-server"]
---> Running in 7f01a4da3209
Removing intermediate container 7f01a4da3209
---> fc26d7967402
Successfully built fc26d7967402
This output shows that in Step 1/3 it takes the base alpine image, in Step 2/3, adds a layer of redis to it and then executes the redis-server command in Step 3/3 whenever the container is started. The RUN command is only executed when the image is is build process.
Further explanation of output is out of the scope of this question.
So when you pull an image from docker hub, it just has the configurations to run the basic requirements. When you need to add your own requirements and configurations to an image, you create a Dockerfile and add dependencies layer by layer on a base image to run it according to your needs.
In simple words I can explain that..as we use certain libraries and node packages for our application in similar way we can use Base Images which are already made and use them with simple search.You can also define your own base image and make use of it.
From Docker docs,
"A container is nothing but a running process, with some added encapsulation features applied to it in order to keep it isolated from the host and from other containers.
One of the most important aspects of container isolation is that *each container interacts with its own private filesystem; this filesystem is provided by a Docker image (like image of any Linux OS - which is also the Base image)." The final image may include multiple layers which are just some other filesystem changes. Like for running a Java application, you put on a JDK layer on top of the Base Linux image.
*Credits: Image taken from Educative.io

Resources