Image Creation, Management, and Registry(Part 2)
Tags: docker, linux, devops, microservices
Published: 2021-09-24 12:20:03

### Tagging Docker Images

Docker tags convey useful information about a specific image version/variant.

They are aliases to the ID of your image which often look like this: 8f5487c8b942

_Assigning tag while building image_

```shell
docker build -t demo:v1 .
```

![tagwhilebuilding](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/66oevbn09oar0jucqwfi.png)

_Assigning tag if no tag default_

Lets build a image without tag.

```shell
docker build .
```

![imagewithouttag](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n9fdul4imevpfqv4fwok.png)
 
Now lets assign tag to the existing image without tag.

```shell
docker tag adc07a47930e demo:v2
```

![tagtonontagimage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9cld0l6hi2x6ppebzl19.png)

_tag for existing tag of the image_

This will create another image with the same IMAGE ID.

```shell
docker tag demo:v2 demo2:v3
```
![existingtagofimage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b256kouqt0fqyxa6f2p1.png)

### Docker Commit

Whenever you make changes inside the container, it can be useful to commit a container’s file changes or settings into a new image.

_By default, the container being committed and its processes will be paused while the image is committed._

Syntax:
```
docker container commit CONTAINER-ID myimage01
```

Created a container containing context01.txt file in root directory.
Then committed the container to the images and then creating another container from the same image, where we can see the same file/changes made present.

![imagecomitting](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8pi3p9ioln0dpubjg8np.png)

We can also define the Commands while committing the images from the containers.

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


command

```shell
docker container commit --change='CMD ["ash"]' modified-container
```

![commandcommit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3tbq76wfliek4up6a5mn.png)

###Docker Image Layers

A Docker image is built up from a series of layers. 
Each layer represents an instruction in the image’s Dockerfile.

Here is the best resource I found for the presentation.

![Docker Layer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1z78h3fi0c3xzo6gde3k.png)

As, the container have the R/W layer a top layer which is connected with the base image.
OR we can say that one base image is connected to different containers by Writable layer.

Lets, see some scenarios. Will build a docker image using dockerfile and will check the layers.

Dockerfile:

```dockerfile
FROM ubuntu
RUN dd if=/dev/zero of=/root/file1.txt bs=1M count=100
RUN dd if=/dev/zero of=/root/file2.txt bs=1M count=100
```

Command to check the layers of the image, where _layerdemo01_ is the image name.

```shell
docker image history layerdemo1
```

Below Screenshot clearly shows how 2 layers are of same volume, as they are not adding the volume of previous layer. Every layer has its separate size according to the command or the changes.

![layerdemo1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k5v63hvqjy8xk5e0l00k.png)

Now, lets try to remove these files and I found that 2 layers were created with *0B* but the image still contains the same *282MB*.

So, Basically here we have 5 layers.
Layer1 -> FROM Ubuntu
Layer2 -> RUN dd if=/dev/zero of=/root/file1.txt bs=1M count=100
Layer3 -> RUN dd if=/dev/zero of=/root/file2.txt bs=1M count=100
Layer4 -> RUN rm -f /root/file1.txt
Layer5 -> RUN rm -f /root/file2.txt

Here Only Layer4 and Layer5 is dealing with the removing of those files, but the file are still there in Layer3 and Layer2.
That is the reason image still have the same volume.

Dockerfile:
```dockerfile
FROM ubuntu
RUN dd if=/dev/zero of=/root/file1.txt bs=1M count=100
RUN dd if=/dev/zero of=/root/file2.txt bs=1M count=100
RUN rm -f /root/file1.txt
RUN rm -f /root/file2.txt
```

![layerdemo2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i87878a7umfaimy78ele.png)
 
For the requirement where we need to remove the files after creation, we can use ***&&*** to run both the command at one-go.
This will conserve the volume of the image

```dockerfile
FROM ubuntu
RUN dd if=/dev/zero of=/root/file1.txt bs=1M count=100 && rm -f /root/file1.txt
RUN dd if=/dev/zero of=/root/file2.txt bs=1M count=100 && rm -f /root/file2.txt
```

### Managing Images using CLI

So basically the best practice of using the command for images is 
```
docker image <command>
```

* docker pull ubuntu == docker image pull ubuntu
* docker images      == docker image ls
* docker image build
* docker image history
* docker image import
* docker image inspect
* docker image load
* docker image prune
* docker image push

![dockerImageCLI](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i3328zrmkkk4ha6w2dxh.png)
 
###Inspecting Docker Images

A Docker Image contains lots of information, some of these  include:

* Creation Date
* Command
* Environment Variables
* Architecture
* OS
* Size

docker image inspect command allows us to see all the information associated with a docker image.

Suppose we need to get the particular field from the inspect data.
e.g _Hostname_

we can use

```shell
docker image inspect ubuntu | grep 'Hostname'
docker image inspect ubuntu --format='{{.Id}}'
```

There are certain things that have parent child details. Like, ContainerConfig have Hostname, Domainname etc.
But, this will only gives the values not the key.

```shell
docker image inspect ubuntu --format='{{.ContainerConfig}}'
```

If you want the key and value both.

```shell
docker image inspect ubuntu --format='{{json .ContainerConfig}}'
```

If you just want the hostname value you can use below caommand to filter out the information from the inspect data.

```shell
docker image inspect ubuntu --format='{{.ContainerConfig.Hostname}}'
```
![imageInspect](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huttfah416t7y0oo259a.png)

###Docker Image prune

Docker image prune command allows us to clean up unused images.
By default, the below command will only clean up dangling images.

***Dangling Images = Image without Tags and Image not referenced by any container***

To prune all the images that has no container refrenced, we can use below commands.

```shell
docker image prune -a
```

If you want to remove all the images only which don't have tag associated, you can use below commands.

```shell
docker image prune
```

Before Prune we had these many images.

![before prune](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p858p1yrkhbqig7x6m57.png)

After running prune command.

![after prune](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ufr24srx8nbityzmgx42.png)
 
Those images got removed which were not referenced to the container. 


Here is the below command the image without the tag ( _<none>_ ) tag which is a Dangling image, but it can't be prune because it has containers associated.

![imageprune](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k9ilj35snt15x8e1vox.png)
 
### Flattening Docker Images

Modifying Image in a single Layer or specific Layer.

As we know ubuntu has many layers. So, to merge all layers to the single layer. There is one approach that to,
*Import and Export to a container*

Commands:

```shell
docker export myubuntu > myubuntudemo.tar
cat myubuntudemo.tar | docker import - myubuntu:latest
```

![layerscompress](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zb563g3p1e8cunng1dyj.png)

### Building Docker Registry

A Registry a stateless, highly scalable server-side application that stores and lets you distribute Docker images.

Docker Hub is the simplest example that all of us must have used.

There are various types of registry available, which includes:

Docker Registry
Docker Trusted Registry
Private Repository (AWS ECR)
Docker Hub

To push the image to a central registry like DockerHub, there are three steps:

* 1. Authenticate your Docker client to the Docker Registry
     Refrence for setting up Docker Registry
     https://hub.docker.com/_/registry/

```shell
docker run -d -p 5000:5000 --restart always --name registry registry:2
```

![setupdockerregistry](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gj55o4pybeg22bgaei5.png)
 
    
* 2. Tag Docker Image with Registry Repository and optional image tag.

```shell
docker tag myubuntu:latest localhost:5000/myubuntu
```

* 3. Push Image using docker push command
    To push the docker image to the ***AWS ECR***.
    Refrence: 
    https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-push-ecr-image.html

```shell
 docker push localhost:5000/myubuntu
```

![dockerpush](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5n9z7p4qfptfv4fe0v6h.png)


Now, lets pull the image from the registry. For that first we need to untag the registy located image and then delete the image.

```shell
docker pull localhost:5000/myubuntu
```
![dockerpull](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fozzdim19jz8ym0mukul.png)

### Pushing Docker Image to Docker Hub

I have my account on Docker Hub and created had 1 repository.

![dockerhubrepo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/03n9xtmtkrod7d94f12m.png)

So, first we will login to the docker hub by CLI and then create the tag and push it. Then before pulling the image I have removed the tag to the image and removed all the containers associated to that container and then pull the image from the Docker Hub Repository.

```shell
docker login
docker tag busybox deepakporwal95/mydemo:v1
docker push deepakporwal95/mydemo:v1
docker pull deepakporwal95/mydemo:v1
```

***Pushing out custom image to docker hub.***

![pushingtodockerhub](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ylb4uxcjgn32jrjenrj.png)

***Pulling the image from Docker Hub.***

![PullingdockerImage](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qkwsup11b3p6wtwdmn6x.png)
 
### Searcing and Filtering Images from Docker Hub

| Description |Command |
|:-----|:--------:|
| Search for Busybox image | docker search busybox |
| Search for Busybox image with Max Result of 5 | docker search busybox --limit 5 |
| Filter only official images | docker search --filter is-official=true nginx |

On searching nginx images.

![searchnginx](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o9x2ttuiivlbf9329vnp.png)

We will limit the number of results.

![limit search](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rqcoejp597zwc844wmw.png)
 

On searching images from Docker Hub we get many results. We can filter those results by three filter supporters.
1. stars
2. is-automated
3. is-official
This will bring to us specific required result only.

![niginx official](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/syjoirsygccneej8ty8b.png)

### Moving Images Across Hosts

Suppose we want to send docker image to other hosts or instances from admin box or master server. In this case we save the image as a zip and then transfer that image to host and at last will load that image in the host.

![movingimageaccroos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u60rh7uyc7emwd82las5.png)


### Cache in Docker

While building a container or image it uses the cache of each layer which has been already been there.

Here is the Dockerfile and requirements.txt details that we will be using for this usecase.

***Dockerfile***
```dockerfile
FROM python:3.7-slim-buster
COPY . .
RUN pip install --quiet -r requirements.txt
ENTRYPOINT ["python", "server.py"]
```

***requirements.txt***
```
certifi==2018.8.24
chardet==3.0.4
Click==7.0
cycler==0.10.0
decorator==4.3.0
defusedxml==0.5.0
```

![Requirements](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/erjzx6gbjfrly9755ncz.png)
 

Here are the commands that will be using to build the images.

```shell
docker build -t without-cache .
docker build -t with-cache .
```

***without cache***

![withoutcache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z2zo5xp70bl1iylv8ux7.png)

***with cache***

![with cache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1tibdgqoxq7027wqohda.png)

References:
[Official Docker](https://docs.docker.com/get-docker/)
[Udemy Course](https://www.udemy.com/course/docker-certified-associate/)

Credit:
[Zeal Vora](https://in.linkedin.com/in/zealvora)

[Prev: Image Creation, Management, and Registry(Part 1)](https://dev.to/dporwal/image-creation-management-and-registry-part-1-pk9)
 
[Next: Docker Networking](https://dev.to/dporwal/docker-networking-5ef0)