Docker: Basics

 

Docker is the underlying technology in the containerization craze sweeping our industry. Should you need multiple containers to mock your infrastructure Docker Swarm, and Kubernetes can be used. For this post, we will be focusing on the very basics of Docker. We will be searching, pulling, creating, and destroying containers. We will also lightly cover volumes, and some cleanup.  

Protip:
I had problems keeping docker working properly in CentOS6. As a result, we will be using CentOS7 for this. If you use CentOS7 as well, do yourself a favor, dont disable firewalld and install iptables-services. Docker does NOT play well with that. The symptom was randomly I couldnt get outbound 443 from inside the continer.
 

Docker [search|pull|run]

Docker images are stored in dockerhub. You can browse the website, or you can type “docker search ".  

Lets find a good image:

[root@prewikka ~]# docker search hello
INDEX       NAME                                                 DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/hello-world                                Hello World! (an example of minimal Docker...   816       [OK]       
docker.io   docker.io/tutum/hello-world                          Image to test docker deployments. Has Apac...   59                   [OK]
docker.io   docker.io/openshift/hello-openshift                  Simple Example for Running a Container on ...   31                   
docker.io   docker.io/google/nodejs-hello                                                                        24                   [OK]
docker.io   docker.io/dockercloud/hello-world                    Hello World!                                    14                   [OK]
docker.io   docker.io/karthequian/helloworld                     A simple helloworld nginx container to get...   12                   [OK]
docker.io   docker.io/nginxdemos/hello                           NGINX webserver that serves a simple page ...   10                   [OK]
docker.io   docker.io/crccheck/hello-world                       Hello World web server in under 2.5 MB          6                    [OK]
docker.io   docker.io/bonomat/nodejs-hello-world                 a simple nodejs hello world container           3                    [OK]
docker.io   docker.io/hello-seattle                              Hello from DockerCon 2016 (Seattle)!            2         [OK]       
docker.io   docker.io/hivesolutions/hello_appier                 Simple hello world application for Appier.      0                    [OK]
docker.io   docker.io/infrastructureascode/hello-world           A tiny "Hello World" web server with a hea...   0                    [OK]
docker.io   docker.io/milsonian/hellohttp                        Basic hello world http app in golang            0                    [OK]
docker.io   docker.io/seabreeze/sbz-helloworld-sidecar           Sidecar hello world example for SeaBreeze.      0                    [OK]
docker.io   docker.io/silasbw/hello                                                                              0                    
docker.io   docker.io/wouterm/helloworld                          A simple Docker image with an Nginx serve...   0                    [OK]
[root@prewikka ~]# docker pull hello-world
Using default tag: latest
Trying to pull repository docker.io/library/hello-world ... 
latest: Pulling from docker.io/library/hello-world
1b930d010525: Pull complete 
Digest: sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Status: Downloaded newer image for docker.io/hello-world:latest
[root@prewikka ~]# 

 
The first relevant container with the highest STARS, is docker.io/hello-world . If you are searching or pulling from docker.io, you dont need to specify the base url. So something like “docker pull silasbw/hello” would work just fine assuming that was the container image you wanted.
 
Now, lets run our image:

[root@prewikka ~]# docker run -it hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

[...]
[root@prewikka ~]# 

 
Our hello-world image ran without an issue. Like the pull command, you would use the non-ambiguous name of the container to run it. Unlike other containers, this container exits after you run it.

Each container has an “entrypoint”. This entrypoint tells the container what to do when it starts. Sometimes it does a task and exits, other times it runs a daemon that keeps going in the background. It all depends on the author, and the purpose of the container. To stop a container manually, type “docker stop $container_id”.
 

Docker [images|ps]

What if we want something different… What if we want a generic centos7 container, and a bash prompt?
 

[root@prewikka ~]# docker pull centos:latest
Trying to pull repository docker.io/library/centos ... 
latest: Pulling from docker.io/library/centos
a02a4930cb5d: Pull complete 
Digest: sha256:184e5f35598e333bfa7de10d8fb1cebb5ee4df5bc0f970bf2b1e7c7345136426
Status: Downloaded newer image for docker.io/centos:latest
[root@prewikka ~]# docker images | grep centos
docker.io/centos                            latest              1e1148e4cc2c        2 months ago        202 MB
docker.io/centos                            6                   b5e5ffb5cdea        6 months ago        194 MB
[root@prewikka ~]# docker run -it centos:latest 
[root@4f9fd46b2e71 /]# 
[root@4f9fd46b2e71 /]# <ctrl+p+q> 
[root@prewikka ~]# 

 
Notice how our bash prompt changed? It shows us we are inside the container. To leave the container running, much like screen, you can detach, using ctrl+p+q. To get it back, we just need to exec something in it.

Lets pretend we didnt have the instance name from the above. We need to find the instance name, and then execute(not to be confused with run) something in the container to re-attach.
 

[root@prewikka ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                                          NAMES
4f9fd46b2e71        centos:latest       "/bin/bash"         3 minutes ago       Up 3 minutes                                                       xenodochial_banach
[root@prewikka ~]# docker exec -it 4f9fd46b2e71 /bin/bash
[root@4f9fd46b2e71 /]# 

 
We used docker ps to find the container id. Then we executed /bin/bash on that container to enter it. Note, your container has to be started and running to be able to exec. So take note of the status column. If your container is not running, you can simply type “docker start $container_id”.
 

Docker Volumes

Volumes are essentially bind mounts back to the host. Lets say I run a container, and I share my /home. That means, from within the container, I can actually access the /home directory available on the host. Each container you use will have its own requirements and customizations. Some require that you pass in a file. Others require you pass in environmental variables. Then there are some that do not take any variables. You just have to look at the container, check it out in dockerhub, and in github.
 

Lets share a volume from the host, to the container

[root@prewikka ~]# mkdir /tmp/some_test_volume
[root@prewikka ~]# echo "blah" > /tmp/some_test_volume/file_in_test_volume
[root@prewikka ~]# docker run -v /tmp/some_test_volume:/root -it centos 
bash-4.2# ls -l /root
total 4
-rw-r--r-- 1 root root 5 Feb  6 21:59 file_in_test_volume
bash-4.2# cat /root/file_in_test_volume 
blah
bash-4.2# 

 
To test this, I create a directory on the host, put a file in it, and then started a container. When I started the container, I used the -v flag. This flag is defined as /path/on/host:/path/in/container. In this case, I made /tmp/some_test_volume <-> /root. So when I checked /root in the container, we were able to see our file. This can be done with a directory, or even specific files. Note, you need to be careful with this. eg: you should never be sharing out your entire /etc.
 

Docker cleanup

When a docker container exits, you can restart it by doing “docker run -it ". This container will still have any changes you made to it. But if you spawn a new container using "docker run -it some/image", you are actually creating a fresh one from the image. To see stopped containers, use "docker ps -a". They tend to build up and need to be removed.  

[root@prewikka ~]# docker ps -a
CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS                       PORTS                                          NAMES
cdb4a7285098        centos                    "/bin/bash"              6 minutes ago       Exited (130) 2 seconds ago                                                  nifty_shannon
35df5aae6917        centos                    "-v /tmp/some_test..."   6 minutes ago       Created                                                                     lucid_volhard
cc6ccc9bdb09        centos:latest             "-v /tmp/some_test..."   6 minutes ago       Created                                                                     brave_engelbart
4f9fd46b2e71        centos:latest             "/bin/bash"              19 minutes ago      Up 19 minutes                                                               xenodochial_banach
5777111f54cb        hello-world               "/hello"                 48 minutes ago      Exited (0) 48 minutes ago                                                   elegant_brahmagupta
c95d49d56cde        centos:6                  "/bin/bash"              5 months ago        Exited (255) 2 months ago                                                   silly_lamarr
[root@prewikka ~]# docker rm cdb4a7285098
cdb4a7285098
[root@prewikka ~]# docker rm 35df5aae6917
35df5aae6917
[root@prewikka ~]#

 
Now, obviously we can’t remove the one instance that is “up”. But we can clear the rest of these out if we wanted to. The command to remove a stopped instance is “docker rm $containerID”.
 
We also need to do this process for images we no longer need:

[root@prewikka ~]# docker images | grep hello
docker.io/hello-world                       latest              fce289e99eb9        5 weeks ago         1.84 kB
[root@prewikka ~]# docker rmi fce289e99eb9
Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container 5777111f54cb
[root@prewikka ~]# docker rm 5777111f54cb
5777111f54cb
[root@prewikka ~]# docker rmi fce289e99eb9
Untagged: docker.io/hello-world:latest
Untagged: docker.io/hello-world@sha256:2557e3c07ed1e38f26e389462d03ed943586f744621577a99efb77324b0fe535
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3
[root@prewikka ~]# 

 
If you currently have a stopped container, it will not let you delete the image. So you must delete the stopped container, and then it will allow you to purge the image. Note, to delete a container you use “docker rm $container_id”. To delete an image, you use “docker rmi $image_id”. The difference is subtle, and worth mentioning.
 
Last, we also need to do this for volumes.

[root@prewikka ~]# docker volume ls
DRIVER              VOLUME NAME
local               0ab98869c6b71c33d270500ddb6815286926d28fc727ec33aa78429c430d1601
local               0f6c5d9e590b1b0dbd72023af2ab582a2817a105ec5b3f0d63780e1221637f01
local               136781f6b499f578dabf22da3f9d643a6e537712f35de273bf720956b791fc3e
local               222f10463ab16b6c72cf139a79044348508e061fbe044975387ef0226ca0616c
local               277aa4fe2e92d53ce25d4999a54f600ecc494e20fb1fd3799e3d1aaf343d331e
local               407248d1e8515e3268b2aacf7a236b7a356c56afc2baa37c3483ad04a82cf263
[...]
local               5a637694b5a83449eacc0e1277beb75996c2b298e4112c0fde0db336ae5d0163
local               eb963b6a301e1c752f85e5ace9e79e38994eb4c494392a656be50c1e0e7ea569
local               ed320e38550c1b6459bfb5dd04d9d40b5c1f4c3689dc2201e16ce119cbbf970d
local               f823a34fcce3083c846abb5e81c9ee4681568ccf0ac0f542e5d2fa74e1fdc16a
local               f8300f7b05e9b156d6fbf1e4ed4460106e025964a929bc5bd07800d6aa867844
local               fe312947a478a72eb1a77abfc8bef8203c8cce4c81588022a8517c635882af4e
[root@prewikka ~]# docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
277aa4fe2e92d53ce25d4999a54f600ecc494e20fb1fd3799e3d1aaf343d331e
676d6f10a5b04068fa71b6c592dfa01a9322824a1503cf185ed1b4a280c86919
eb19fc060e95a46976dab83f243a4b54824275b2a638f825e6d44d4a7f2a380d
407248d1e8515e3268b2aacf7a236b7a356c56afc2baa37c3483ad04a82cf263
[...]
c19e154919e2e039eb4cb2d59a665b0d1ae840d4b92cd776c6c349c66749114b
cb2eddc898623110f19d764b4ecaa82747eae949ccad50330959eba8a100170a
eb963b6a301e1c752f85e5ace9e79e38994eb4c494392a656be50c1e0e7ea569
905f26329e061141951ba20acf7296377908a01eb5297b51b9009ae25e44892d
91863d064587a51f5986f9e1395d7536651ffc0bc4f8eb71c434fa1c66716f77
b8bbb0eb59744671d71cf6d37212ca04b8b7711222902b536df52f4ada0040e9
cb584c8cbabef11fc9589c55d1c9db2ec22da40fe90a4f11b3502e8dff38c41d
5a637694b5a83449eacc0e1277beb75996c2b298e4112c0fde0db336ae5d0163

Total reclaimed space: 11.26 GB
[root@prewikka ~]#

 
The space goes quite fast as you create and delete instances. This is not necessarily tied to passing it -v. Each containter will create a volume to exist. You can also do fancy stuff like share volumes between them.
 

Conclusion

Containerization is already becoming a big thing. Docker gets used for Continuous Integration, Sandboxing, Development Testing, Quality Control, etc. The limits are entirely up to what you can imagine. Once you master this, you should consider Docker Swarm, or Kubernetes as your next stop.