10. DevOps: How to Build images from Docker containers?

Docker-logo

This is in continuation of my last blog “9. DevOps: How to do Containers housekeeping ?”. In this blog I would like to demonstrate on:

How to Build images from docker containers?:

Note: If you want to recollect the docker commands to be used during your current lab practice, visit my blog link:

https://vskumarblogs.wordpress.com/2017/12/13/some-useful-docker-commands-for-handling-images-and-containers/

So far we have built the containers and operated them through the previous exercises. Now, let us see how  can we add  software to our base image on a running container and then convert that container into an image for future usage.

Let’s take ubuntu:16.04 as our base image, install the wget application, and then convert the running container to an image with the below steps:

To make ubuntu:16.04 container is our base image, we need to install the wget application, and then convert it as the running container to a docker image by using the below steps:

  1. Launch an ubuntu:16.04 container using the docker run subcommand, as shown below:
      $ sudo docker run -i -t ubuntu:16.04 /bin/bash
========================>
vskumar@ubuntu:~$ sudo docker ps -aq
155f4b0764b1
vskumar@ubuntu:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
155f4b0764b1        ubuntu:16.04        "/bin/bash"         2 hours ago         Up 11 minutes                           zen_volhard
vskumar@ubuntu:~$ sudo docker run -i -t ubuntu:16.04 /bin/bash
root@3484664d454a:/# 
=========================>
2. Now, let's  verify is wget  available for this image or not.
============== the display shows there is no wget in this image =========>

root@3484664d454a:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
root@3484664d454a:/# which wget
root@3484664d454a:/# 

      root@472c96295678:/# apt-get update
==================>
As we know that it is a brand new ubuntu container we built it, before installing wget we must synchronize it with the Ubuntu package repository, as shown below:
====================>
root@3484664d454a:/# apt-get update
Get:1 http://archive.ubuntu.com/ubuntu xenial InRelease [247 kB]         
Get:2 http://security.ubuntu.com/ubuntu xenial-security InRelease [102 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates InRelease [102 kB]                                                                      
Get:4 http://archive.ubuntu.com/ubuntu xenial-backports InRelease [102 kB]                                                                    
Get:5 http://archive.ubuntu.com/ubuntu xenial/universe Sources [9802 kB]                                                                      
Get:6 http://security.ubuntu.com/ubuntu xenial-security/universe Sources [53.1 kB]                                                            
Get:7 http://security.ubuntu.com/ubuntu xenial-security/main amd64 Packages [504 kB]                                                          
Get:8 http://security.ubuntu.com/ubuntu xenial-security/restricted amd64 Packages [12.9 kB]                                                   
Get:9 http://security.ubuntu.com/ubuntu xenial-security/universe amd64 Packages [229 kB]                                                      
Get:10 http://security.ubuntu.com/ubuntu xenial-security/multiverse amd64 Packages [3479 B]                                                   
Get:11 http://archive.ubuntu.com/ubuntu xenial/main amd64 Packages [1558 kB]                                                                  
Get:12 http://archive.ubuntu.com/ubuntu xenial/restricted amd64 Packages [14.1 kB]                                                            
Get:13 http://archive.ubuntu.com/ubuntu xenial/universe amd64 Packages [9827 kB]                                                              
Get:14 http://archive.ubuntu.com/ubuntu xenial/multiverse amd64 Packages [176 kB]                                                             
Get:15 http://archive.ubuntu.com/ubuntu xenial-updates/universe Sources [228 kB]                                                              
Get:16 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 Packages [864 kB]                                                           
Get:17 http://archive.ubuntu.com/ubuntu xenial-updates/restricted amd64 Packages [13.7 kB]                                                    
Get:18 http://archive.ubuntu.com/ubuntu xenial-updates/universe amd64 Packages [711 kB]                                                       
Get:19 http://archive.ubuntu.com/ubuntu xenial-updates/multiverse amd64 Packages [18.5 kB]                                                    
Get:20 http://archive.ubuntu.com/ubuntu xenial-backports/main amd64 Packages [5174 B]                                                         
Get:21 http://archive.ubuntu.com/ubuntu xenial-backports/universe amd64 Packages [7135 B]                                                     
Fetched 24.6 MB in 59s (412 kB/s)                                                                                                             
Reading package lists... Done
root@3484664d454a:/# 
================================>
Now, we can install wget as below:
=========== Output of wget installation on container ===========>

root@3484664d454a:/# 
root@3484664d454a:/# apt-get install -y wget
Reading package lists... Done
Building dependency tree        
Reading state information... Done
The following additional packages will be installed:
  ca-certificates libidn11 libssl1.0.0 openssl
The following NEW packages will be installed:
  ca-certificates libidn11 libssl1.0.0 openssl wget
0 upgraded, 5 newly installed, 0 to remove and 1 not upgraded.
Need to get 2089 kB of archives.
After this operation, 6027 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libidn11 amd64 1.32-3ubuntu1.2 [46.5 kB]
Get:2 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 libssl1.0.0 amd64 1.0.2g-1ubuntu4.9 [1085 kB]
Get:3 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 openssl amd64 1.0.2g-1ubuntu4.9 [492 kB]
Get:4 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 ca-certificates all 20170717~16.04.1 [168 kB]
Get:5 http://archive.ubuntu.com/ubuntu xenial-updates/main amd64 wget amd64 1.17.1-1ubuntu1.3 [299 kB]
Fetched 2089 kB in 4s (421 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libidn11:amd64.
(Reading database ... 4768 files and directories currently installed.)
Preparing to unpack .../libidn11_1.32-3ubuntu1.2_amd64.deb ...
Unpacking libidn11:amd64 (1.32-3ubuntu1.2) ...
Selecting previously unselected package libssl1.0.0:amd64.
Preparing to unpack .../libssl1.0.0_1.0.2g-1ubuntu4.9_amd64.deb ...
Unpacking libssl1.0.0:amd64 (1.0.2g-1ubuntu4.9) ...
Selecting previously unselected package openssl.
Preparing to unpack .../openssl_1.0.2g-1ubuntu4.9_amd64.deb ...
Unpacking openssl (1.0.2g-1ubuntu4.9) ...
Selecting previously unselected package ca-certificates.
Preparing to unpack .../ca-certificates_20170717~16.04.1_all.deb ...
Unpacking ca-certificates (20170717~16.04.1) ...
Selecting previously unselected package wget.
Preparing to unpack .../wget_1.17.1-1ubuntu1.3_amd64.deb ...
Unpacking wget (1.17.1-1ubuntu1.3) ...
Processing triggers for libc-bin (2.23-0ubuntu9) ...
Setting up libidn11:amd64 (1.32-3ubuntu1.2) ...
Setting up libssl1.0.0:amd64 (1.0.2g-1ubuntu4.9) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 /usr/local/share/perl/5.22.1 /usr/lib/x86_64-linux-gnu/perl5/5.22 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.22 /usr/share/perl/5.22 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.)
debconf: falling back to frontend: Teletype
Setting up openssl (1.0.2g-1ubuntu4.9) ...
Setting up ca-certificates (20170717~16.04.1) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 76.)
debconf: falling back to frontend: Readline
debconf: unable to initialize frontend: Readline
debconf: (Can't locate Term/ReadLine.pm in @INC (you may need to install the Term::ReadLine module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.22.1 /usr/local/share/perl/5.22.1 /usr/lib/x86_64-linux-gnu/perl5/5.22 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.22 /usr/share/perl/5.22 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base .) at /usr/share/perl5/Debconf/FrontEnd/Readline.pm line 7.)
debconf: falling back to frontend: Teletype
Setting up wget (1.17.1-1ubuntu1.3) ...
Processing triggers for libc-bin (2.23-0ubuntu9) ...
Processing triggers for ca-certificates (20170717~16.04.1) ...
Updating certificates in /etc/ssl/certs...
148 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
root@3484664d454a:/# 
=========================== End of installation ===========>
Now, we can verify with  'which wget ' command
============>
root@3484664d454a:/# which wget
/usr/bin/wget
root@3484664d454a:/# 
============>
Please let us recollect; installation of any software would alter the Dockwer base image composition. In which, we can also trace using the docker diff subcommand as we did in the previous exercises. 
I will open a second Terminal/screen, the docker diff subcommand can be issued from it, as below:
      $ sudo docker diff 472c96295678
===============>
vskumar@ubuntu:~$  
vskumar@ubuntu:~$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
3484664d454a        ubuntu:16.04        "/bin/bash"         15 minutes ago      Up 15 minutes                           jolly_cray
155f4b0764b1        ubuntu:16.04        "/bin/bash"         2 hours ago         Up 40 minutes                           zen_volhard
vskumar@ubuntu:~$ sudo docker diff 155f4b0764b1
C /root
A /root/.bash_history
vskumar@ubuntu:~$ 
============>

How to save this container ?:
The docker commit subcommand can be performed on a running or a stopped container. When a commit is performed on a running container, the Docker Engine pauses the container during the commit operation in order to avoid any data inconsistency. 
Now we can stop our running container.
We can commit a container to an image with the docker commit subcommand, as shown here:
      $ sudo docker commit 

================== Using commit for container ============>

root@3484664d454a:/# 
root@3484664d454a:/# exit
exit
vskumar@ubuntu:~$ sudo docker commit 3484664d454a
[sudo] password for vskumar: 
Sorry, try again.
[sudo] password for vskumar: 
sha256:fc7e4564eb928ccfe068c789f0d650967e8d5dc42d4e8d92409aab6614364075
vskumar@ubuntu:~$ 
=======================>
You can see the container id from the above output.

=========== We can also give a message to the commit command as below ===>
vskumar@ubuntu:~$ sudo docker commit 3484664d454a  Docker-exercise/ubuntu-wgetinstall
invalid reference format: repository name must be lowercase
vskumar@ubuntu:~$ sudo docker commit 3484664d454a  docker-exercise/ubuntu-wgetinstall
sha256:e34304119838d79da60e12776529106c350b1972cd517648e8ab90311fad7b1a
vskumar@ubuntu:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                       PORTS               NAMES
3484664d454a        ubuntu:16.04        "/bin/bash"         24 minutes ago      Exited (130) 6 minutes ago                       jolly_cray
155f4b0764b1        ubuntu:16.04        "/bin/bash"         2 hours ago         Up About an hour                                 zen_volhard
vskumar@ubuntu:~$ 
===================== Note there are two containers created  ====>
Now, I want to remove one container :
==========>

vskumar@ubuntu:~$ sudo docker rm 3484664d454a
3484664d454a
vskumar@ubuntu:~$ sudo docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
155f4b0764b1        ubuntu:16.04        "/bin/bash"         3 hours ago         Up About an hour                        zen_volhard
vskumar@ubuntu:~$ 
========================>

Now let us check the docker images how many we have in our store :
=========== List of images ==========>
vskumar@ubuntu:~$ 
vskumar@ubuntu:~$ sudo docker images
REPOSITORY                           TAG                 IMAGE ID            CREATED             SIZE
docker-exercise/ubuntu-wgetinstall   latest              e34304119838        5 minutes ago       169MB
<none>                               <none>              fc7e4564eb92        7 minutes ago       169MB
hello-world                          latest              f2a91732366c        5 days ago          1.85kB
ubuntu                               16.04               20c44cd7596f        8 days ago          123MB
ubuntu                               latest              20c44cd7596f        8 days ago          123MB
busybox                              latest              6ad733544a63        3 weeks ago         1.13MB
busybox                              1.24                47bcc53f74dc        20 months ago       1.11MB
vskumar@ubuntu:~$ 

==============================>
How to remove images:

by using :

sudo docker rmi image [image id], we can remove the image. For example; if you want to remove the image id:
47bcc53f74dc
you can use: $ sudo docker rmi image 47bcc53f74dc
=================>
vskumar@ubuntu:~$ sudo docker rmi image 47bcc53f74dc
Untagged: busybox:1.24
Untagged: busybox@sha256:8ea3273d79b47a8b6d018be398c17590a4b5ec604515f416c5b797db9dde3ad8
Deleted: sha256:47bcc53f74dc94b1920f0b34f6036096526296767650f223433fe65c35f149eb
Deleted: sha256:f6075681a244e9df4ab126bce921292673c9f37f71b20f6be1dd3bb99b4fdd72
Deleted: sha256:1834950e52ce4d5a88a1bbd131c537f4d0e56d10ff0dd69e66be3b7dfa9df7e6
Error: No such image: image
vskumar@ubuntu:~$ 
=================>
 

So by using :

sudo docker rmi image [image id], we can remove the image.  Just recollect the difference between the image removal and container removal. For containers removal refer to my blog on "Housekeeping containers". Now we have learned how to create an image from containers using a few easy steps by installing the wget application. You can also add some other software applications to the same or different container(s) in the similar way.

You can use this method for testing also.  Let us say, you want to test a set of java programs. Then you need to install jdk and copy your programs. Write a shell script to compile and execute the programs by piping their output into a text file in a Linux background. So this way, you will be using the container as a test environment also.

The most easy and recommended way of creating an image is to use the Dockerfile method.

Within dockerfile we can mention the setup required to build a container through different steps. Then dockerfile creates the required setup for a container, under docker’s building activity.

We will see it in future exercises.

Please leave your feedback!

Vcard-Shanthi Kumar V-v39. DevOps: How to do Containers housekeeping ?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s