Learning Docker

Learning Docker

I finally decided to learn docker, being a fun of linux academy tutorials it was a no-brainer to go through their docker training. Unfortunately they don't have any notes to accompany the video training, so i decided to write my own and publish it hopefully it will help others going through the docker training.

Installing Docker on Ubuntu 14.04

 apt-get update
 apt-get install apt-transport-https ca-certificates
 sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
 nano /etc/apt/sources.list.d/docker.list
 apt-get update
 apt-get install linux-image-extra-$(uname -r)
 apt-get install apparmor
 apt-get install docker-engine
 service docker start
The option version will display the docker version
 docker version
To search for available containers
docker search centos
 docker search nginx
To get an image
docker pull nginx
To view available docker containers on your system
docker images

Going inside a container

docker run -i -t centos /bin/bash
docker run -i -t centos:latest /bin/bash

Commit a customized Container once you have modified it

docker commit -m="Added json module for ruby" -a="Stelios" cae13561f52d liuxadademy/sinimage:v1.1
docker run -i -t liuxadademy/sinimage:v1.1 /bin/bash

Packaging a Customized Container

mkdir linuxacademy
nano Dockerfile 
#Custom dockerfile build
FROM ubuntu:latest
MAINTAINER Linux Academy <stelios@milidonis.com>
RUN apt-get update
RUN apt-get install -y ruby ruby-dev
docker build -t="ubuntu:latest" .
docker images
docker run -i -t ubuntu:latest /bin/bash
Running container commands within ocker

docker ps --- shows running containers

docker run ubuntu:latest /bin/echo 'helo from docker'
helo from docker

docker run -d ubuntu:latest /bin/bash "while true; do echo fddman; sleep 1; done"

docker logs amazing_mcnulty

docker stop amazing_mcnulty


Lecture: Exposing Our Container With Port Redirects

run the container and start services forwarding port 8080 on server to 80 in the container
docker run -d -p 8080:80 tutum/apache-php

Lecture: Attach to a Running Container

grab snapshot of a container instance and commit it so the changes made to it are saved
docker commit e1238b6a84f1 centos6:withupdates
with the d option you demonize the container instance and keep it running
 docker run -itd centos6:withupdates /bin/bash
docker ps
03b807ebedd0 centos6:withupdates "/bin/bash" 26 seconds ago Up 26 seconds grave_turing
doing a docker ps will show that the container is running bin/bash,

to identify the ip you can simply run

docker inspect grave_turing
 "Gateway": "",
 "IPAddress": "",
 "IPPrefixLen": 16,
 "IPv6Gateway": "",
 "GlobalIPv6Address": "",
 "GlobalIPv6PrefixLen": 0,
 "MacAddress": "02:42:ac:11:00:02"


The docker attach command allows you to attach to a running container using the container’s ID or name, either to view its ongoing output or to control it interactively. You can attach to the same contained process multiple times simultaneously, screen sharing style, or quickly view the progress of your detached process.So since we have passed "d" option previously we can now attach to that container since its running.

docker attach sleepy_bassi


Lecture: Removing Images



 docker images

centos6 withupdates 8698ee40c98c 50 minutes ago 371.6 MB
newcentos ithapache 05d85d398323 5 hours ago 346.3 MB
ubuntu latest 44776f55294a 4 days ago 120.1 MB
centos 6 fc73b108c5ae 3 weeks ago 228.9 MB

we wanto to remove the centos:6 image, however we cant because the other containers are dependent on that image. This is how docker works , once you modify a container and commit it , it depends on the parent container


docker rmi fc73b108c5ae
Error response from daemon: conflict: unable to delete fc73b108c5ae (cannot be forced) - image has dependent child images

we have to remove the dependencies firtst. A sucessfull remove looks like this:

docker rmi 05d85d398323 Untagged: newcentos:ithapache Deleted: sha256:05d85d398323f2e04511f4c19dc92f4326a647b9c32504976c15095bb8b0c52b Deleted: sha256:801f5a5f83915ca1bbe33c9b6e6c4a621da251eea3102d0d6383fdaa8cfb60ff

Lecture: Directory Structure

Now that we have built images, containers, Dockerfile deployments and demonstrated removing them, we will step back and visit the Docker setup and directory structure. We will show how to use Linux to view the JSON configuration files and what they mean as well as how to delete a large number of containers safely so you can remove the underlying images (preventing us from accidentally orphaning our containers).

location of the decker files and containers is in /var/lib/docker/

ls /var/lib/docker
4 drwx------. 10 root root 4096 Apr 29 16:00 containers
0 drwx------. 5 root root 50 Apr 29 10:37 devicemapper
0 drwx------. 3 root root 25 Apr 29 10:32 image
0 drwxr-x---. 3 root root 18 Apr 29 10:32 network
0 drwx------. 2 root root 6 Apr 29 10:42 tmp
0 drwx------. 2 root root 6 Apr 29 10:32 trust
0 drwx------. 2 root root 24 Apr 29 10:32 volumes

In the file /var/lib/docker/image/devicemapper/repositories.json you will find the container names on the system , its a reference file that can be edited. If you for example see "none " after the docker images command you may edit this file to fix that.

 "Repositories": {
 "centos": {
 "centos:6": "sha256:fc73b108c5ae69424c1eec34499a74e8a0f17716a706d0813bccfeba5d9a8fbb"
 "centos6": {
 "centos6:withupdates": "sha256:8698ee40c98cc55faedf16d8d3584a960d5370aa411c8472208ba0011f8b28df"
 "ubuntu": {
 "ubuntu:latest": "sha256:44776f55294a30e89d6a348d3b3ba50576f5fe29d4b8d28d74699e87dfecc7c5"


inside the container directory we find the containers and their directories.Navigating inside the directory of one container we see the following


03b807ebedd0ff2c4d8ac0f4b3833d76a856790ed77a3a0d94d1526508d4323d]# ls -la
total 36
drwx------   3 root root 4096 Apr 29 15:48 .
drwx------. 10 root root 4096 Apr 29 16:00 ..
-rw-r-----   1 root root 1242 Apr 29 15:58 03b807ebedd0ff2c4d8ac0f4b3833d76a856790ed77a3a0d94d1526508d4323d-json.log
-rw-r--r--   1 root root 2363 Apr 29 15:58 config.v2.json
-rw-r--r--   1 root root 1053 Apr 29 15:58 hostconfig.json
-rw-r--r--   1 root root   13 Apr 29 15:48 hostname
-rw-r--r--   1 root root  174 Apr 29 15:48 hosts
-rw-r--r--   1 root root   75 Apr 29 15:48 resolv.conf
-rw-------   1 root root   71 Apr 29 15:48 resolv.conf.hash
drwx------   2 root root    6 Apr 29 15:48 shm

The .log file contains the information we see when we run "docker logs" on a runing container

the config file list the initial configuration for when the container was build


Lecture: Services That Run on Startup

Up to now, we have made changes to our containers and added services to them. However, a container is not a full OS and as such is not bound by services or init levels in order to start services on container start. We will talk about a couple of methods that can be used to start normal services in our container when started.
Using bashrc
To make an application start automatically in a container we can edit the .bashrc file inside root hoem directory and make its as follows


# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc

#start the apache web service
/sbin/service httpd start

this will start the apache web server.

Then we must commit the image to save changes

docker commit 01b4b6ea00a6 cento6:apacherunning

then run the container with the daemon option

docker run -itd cento6:apacherunning /bin/bash
2)Create a script to run from bashrc
We create a bash script in /usr/bin

rm -rf /run/httpd/* #remove pid

exec /usr/sbin/apachectl -D FOREGROUND

we then add the location of that script in .bashrc


# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc

#start the apache web service
#/sbin/service httpd start

again we commit the changes

docker commit 3780e4e4078e centos6:script


and run


docker run -itd centos6:script /bin/bash



Lecture: Dockerfile: Tying It Together

We have now spent a good amount of time building, one function at a time, our images and containers. We have been introduced to the Dockerfile to build a new image, now we are going to look at it in depth. We will use what we have done one step at a time previously and put it all in one place. We will also talk about how Dockerfile works related to how we have proceeded manually up to now.

We first create a file, lets call it dockerfile and inside we add the following

FROM centos:centos6 #start  with this base image if it doesnt exist it wil$
MAINTAINER Stelios <stelios@milidonis.com> 

#get updates and install apache, clean up and append to    the index.html 
RUN yum    -y update; yum clean all
RUN yum    -y install httpd
RUN echo "This is an pache test site" >> /var/www/html/index.html

#allow listening to port 80

#append    to bashrc the command to start apache
RUN echo "/sbin/service httpd start" >>    /root/.bashrc

Then we run the following command within the directory where the file exists

 docker build -t stelios:centos6 .


What will happen is that the centos container will be downloaded, then within that container the update will run, apache will be installed , the bashrc file will be edited and then the final container will be commited. If we run docker images we will now see the container available

Then we run the container

run -itd stelios:centos6 /bin/bash

and we can see the container run with docker ps

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
72d81f9c4463        stelios:centos6     "/bin/bash"       4 seconds ago       Up 3 seconds        80/tcp              determined_torvalds


Lecture: Pushing Images to Docker Hub

We have a number of images on our local system. However, there is a particular naming convention that needs to be used when compiling an image to be uploaded. We will talk about that format and then demonstrate how to push our images to our repositories online.

In the previous guide i build an image, it is importand that the maintainer must much your docker username and email address in order to successfully publish to docker hub

MAINTAINER stelios <stelios@milidonis.com>

when we build the image we must use our username followed by / and then give it a release name, in the eample below i am calling it beta1.

docker build -t stelios/centos6:beta1 .

First login to docker using the command bellow nd you will be prompted for your username and password

docker login

After your authenticated you can push to your repo using the following


docker push stelios/centos6:beta1


In your docker hub account you will after the upload is complete be ble to view you uploaded container. You can make it private so its not viewed by others. Remember your container will show up in people searhes so do remove it after this step.

[caption id="attachment_52" align="alignnone" width="687"]docker hub docker hub[/caption]

Lecture: Adding External Content

When building our images in the past, we have only pulled in content and applications that was available online through normal Linux repositories. Now, we are going to build a new container that inherits from our application base and include external content that can be distributed with the new images.

First we edit the /root/build/dockerfile

FROM centos:centos6
 #start with this base image if it doesnt exist it will download it
MAINTAINER stelios <stelios@milidonis.com>
ADD testfile.html /var/www/html/testfile.html

We create a simple html file in /root/build/testfile.html we can put anything in it:

<h1>THIS IS A TEST </h1>

Then we create the container and call it test:html

 docker build -t test:html .

We can then see in out images the container instance has been created, and when we start the conatiner we will have the file in the directory specidied

docker run -it test:html /bin/bash

[root@9fb8e08ef099 /]# cat /var/www/html/testfile.html


Lecture: Image Volume Management

Up until now, everything we worked with in our container was just that - IN our container. In this video, we will start showing you how to expose external resources to your running containers, why you might do so and demonstrate the live benefits of the process.

Using the "-v " option we can mount in a container a volume

docker run -it -v /myapp test:html /bin/bash

this wil appear in the container as:

 10G 272M 9.8G 3% /
tmpfs 737M 0 737M 0% /dev
tmpfs 737M 0 737M 0% /sys/fs/cgroup
 29G 2.6G 26G 10% /myapp
 29G 2.6G 26G 10% /etc/resolv.conf
 29G 2.6G 26G 10% /etc/hostname
 29G 2.6G 26G 10% /etc/hosts
shm 64M 0 64M 0% /dev/shm
tmpfs 737M 0 737M 0% /proc/kcore
tmpfs 737M 0 737M 0% /proc/timer_stats
tmpfs 737M 0 737M 0% /proc/sched_debug

The following will map a directory from the os to the container.We create a directory /root/myvol that will then appear as /var/volume in the container as well as its contents.Notice what happens when the var/volume folder is checked after runing the container.

run -it -v /root/myvol/:/var/volume test:html /bin/bash
[root@localhost ~]# cd myvol/
[root@localhost myvol]# touch test
[root@localhost myvol]# docker run -it -v /root/myvol/:/var/volume test:html /bin/bash
[root@d6cb9c65e9f9 /]# cd /var/volume/
[root@d6cb9c65e9f9 volume]# ls

This is an easy way to give access to a local folder to your container , and that folder can be shared among containers.


Another useful example if we add an html file in the OS /root/myvol/test.html..This wll mount the local operating systems /root/myvol directory containing the html file to container /var/www/html .

run -itd -v /root/myvol/:/var/www/html test:html /bin/bash

Any changes done inside the /root/myvol/ will be imediately reflected in the container

Lecture: Advanced Container Network Management

Advanced command line options for managing our containers network configuration. Up until now, we have accepted name, IP and configuration defaults for each container that we have launched - now we learn how to take control of what we run on our network!


Docker creates an interface that manges the ip's for the containers

 docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
 link/ether 02:42:59:f1:cb:3a brd ff:ff:ff:ff:ff:ff
 inet scope global docker0
 valid_lft forever preferred_lft forever
 inet6 fe80::42:59ff:fef1:cb3a/64 scope link

you cannot set a static ip when you launch a container

We are going to change the ip's network range for the docker containers

First we need to stop the docker service

systemctl stop docker

Then we create and link an interface type bridge . So we create a bridge and call it br10


ip link add br10 type bridge

We then give it an ip range

ip addr add dev br10


now we have

 br10: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN 
 link/ether 2e:01:71:3a:3d:a6 brd ff:ff:ff:ff:ff:ff
 inet scope global br10
 valid_lft forever preferred_lft forever

we need to bring it UP


ip link set br10 up
br10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN 
 link/ether 2e:01:71:3a:3d:a6 brd ff:ff:ff:ff:ff:ff
 inet scope global br10
 valid_lft forever preferred_lft forever
 inet6 fe80::2c01:71ff:fe3a:3da6/64 scope link 
 valid_lft forever preferred_lft forever


Now we need to tell docker to use that bridge adapter instead of docker0. This is done on a systemd server


/usr/bin/docker daemon -b br10

If we opena container now we will see that the container will get an ip in the range

To make the changes permanent , we edit the /etc/network/interfaces file and we add

auto lo
iface lo inet loopback
auto br10
iface br10 inet static
bridge_ports dummy0
bridge_stp off
bridge_fd 0


Lecture: Interactive Shell Control

We will take a deeper dive into our Interactive Shell Prompt when starting containers. The viewer will learn how to detach and attach to running containers as well as restart a container in the same state it was stopped in.


Naming your container
 docker run -it --name MYCONTAINER test:html /bin/bash

you will see the container now is called "MYCONTAINER" instead of a generated name

docker ps
38726da2131e test:html "/bin/bash" 7 seconds ago Up 5 seconds 80/tcp MYCONTAINER


Running a command from outside the container to the container
First we deamonize the container
docker run -itd --name MYCONTAINER1 test:html /bin/bash

Then we execute a command from the os to the container

docker exec -it MYCONTAINER1 /usr/bin/top


we will get top for the container, so we connect to teh container and running a process to the tti of the host.

Lecture: Previous Container Management

We explore the way to interact directly with previously run containers. We will show how to get their names and IDs and then how to restart them even after they have been stopped.

To get a list of all the docker containers that have run in the past as well as the currnt ones

docker ps -a
11346db3740c test:html "/bin/bash" 7 minutes ago Up 7 minutes 80/tcp MYCONTAINER1
38726da2131e test:html "/bin/bash" 12 minutes ago Exited (0) 7 minutes ago MYCONTAINER
3159dae75f28 test:html "/bin/bash" 17 minutes ago Exited (127) 14 minutes ago loving_spence
ee14b6360af7 test:html "/bin/bash" 17 hours ago Exited (137) 16 hours ago nostalgic_mccarthy
d6cb9c65e9f9 test:html "/bin/bash" 17 hours ago Exited (0) 17 hours ago stupefied_nobel
da9f269a3db4 test:html "/bin/bash" 17 hours ago Exited (0) 17 hours ago admiring_spence
ff1b2e9ba93f test:html "/bin/bash" 17 hours ago Exited (0) 17 hours ago awesome_easley
9fb8e08ef099 test:html "/bin/bash" 18 hours ago Exited (0) 17 hours ago focused_meitner
72d81f9c4463 57d081a803b8 "/bin/bash" 4 days ago Exited (137) 4 days ago determined_torvalds
63cfe4f13cb1 centos6:script "/bin/bash" 6 days ago Exited (137) 17 hours ago modest_jang
3780e4e4078e centos6:withupdates "/bin/bash" 6 days ago Exited (0) 6 days ago silly_hugle
0546df7913ae cento6:apacherunning "/bin/bash" 6 days ago Exited (137) 6 days ago big_archimedes
01b4b6ea00a6 8698ee40c98c "/bin/bash" 6 days ago Exited (0) 6 days ago jolly_wozniak
236d9514484f 8698ee40c98c "/bin/bash" 6 days ago Exited (0) 6 days ago sleepy_bassi
03b807ebedd0 8698ee40c98c "/bin/bash" 6 days ago Exited (0) 6 days ago grave_turing
254eb9fbfe10 8698ee40c98c "/bin/bash" 6 days ago Exited (0) 6 days ago goofy_colden
e1238b6a84f1 9a61e0b7ef68 "/bin/bash" 6 days ago Exited (0) 6 days ago lonely_bose
80ed8528ddda centos:6 "/bin/bash" 6 days ago Exited (0) 6 days ago pensive_kowalevski
09fe89da7eb0 centos:6 "/bin/bash" 6 days ago Exited (0) 6 days ago grave_swartz
a591a0c3ec3a centos:6 "/bin/bash" 6 days ago Exited (0) 6 days ago backstabbing_cori


What we can do with this information is we can start any of those containers again at the same status it was.

docker start big_archimides

[root@localhost ~]# docker start big_archimedes

and then we can attach to that container and run commands

docker attach big_archimedes

Because containers remain we can kill them of , they clutter our system

If we want to remove all containers that are 6 days old we can do teh following

docker ps -a | grep '6 days ago' | awk '{print$1}' | xargs docker rm

Lecture: Container Routing

We have talked about how to give our hosted system access to container network resources by pulling the container IP from the JSON configuration as well as exposing network service ports or remapping them to local ports. In this video, we explore two methods of making your container resources available to other nodes on your local network and behind the firewall by accessing common Linux network management functions or through your local router interface.


One wy of accessing the container from another machine that sist on the local network as the host is to modify the settings on that machine so as whe you give it the ip of the container to lookup the host os ip instead.

So if the host os ip is and the container is and we are trying tp access the container from another machine that is on another ip for example then on that machine we run the following command

route add -net netmask gw

so we are telling our machine for any ip in the network go to gateway 192,168.0.16 an lookup that machine.

This is only usefull on that machine , we can set this setting on our router and give it a rule for the entire internal network.(example below show setup on dd-wrt router)

Screenshot from 2016-05-06 16:26:27

we can see now when we do a traceroute

traceroute to (, 30 hops max, 60 byte packets
 1 ( 0.606 ms 0.601 ms 0.602 ms
 2 ( 1.137 ms 1.139 ms 1.128 ms

Lecture: Sharing Container Resources

We have previously introduced volume management with containers as it pertains to the underlying operating system and sharing mounts. Now we will explore how containers can be linked together to share their underlying filesystems.

We are going to look at how container can share files between each other.The first step we run a container and in it we attach a volume that we will call /data


docker run -dti -v /data --name DATA1 stelios:centos6 /bin/bash

Then we run a second container but instead of adding a volume we reference the volume from the previous container

docker run -dti --volumes-from DATA1 --name DATA2 stelios:centos6 /bin/bash

So now we have the two containers running

docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
772dcdac2fb7        stelios:centos6     "/bin/bash"         2 minutes ago       Up 2 minutes        80/tcp              DATA2
b63e15081295        stelios:centos6     "/bin/bash"         7 minutes ago       Up 7 minutes        80/tcp              D

So now the two containers are sharing the same folder /data and are linked by that filesystem.Anything you write in /data in one container its seen by the other and vice versa

Lecture: Committing a Running Container (Snapshot Images)

Up to now, we have built containers and base images by running a container, making some changes, ending the container and then committing those changes rolling them into a new base image. Now, we will show how to commit changes in a running container which can be used to provide in flight snapshots of periodic changes for development, version control, version testing and more.

Lets say we have a running container upon which a package isnt installed.We install a apckage on that container and while the container is running we can simply comming the changes for that container and give it another name

docker ps

a742831c9a01 centos:centos6 "/bin/bash" 36 seconds ago Up 35 seconds jolly_northcutt

[root@localhost ~]# docker commit jolly_northcutt centos6:which

so we see the container "jolly_northcut" is running and while its running we do a commit and save the container as centos:which

This way we take snapshots of a running container

We can use this in a development enviroment where we can have a script that takes snaphosts of running containers every 15 minutes and names them incrimentally , so we can roll back e.t.c

Only the changes are written when a commit is done , so this saves storage space

Lecture: Container Linking and Communication

Now that we have the fundamentals of communicating through port redirects and shared volumes, we can explore some of the more in depth methods of linking containers. In this video, we will explicit link together two containers so that they can securely share information amongst themselves about their IPs, applications and ports all automatically and through environment variables.


First step we start a container

docker run -itd --name mywebserver stelios:centos6 /bin/bash


Then we start a second container and we link that to the previous container.

docker run -it --name mytestcontainer1 --link mywebserver stelios:centos6 /bin/bash

What happens is that the two containers now know of each others existance and they are network linked together.

These two containers can now communicate with each other via known ports and ip's that arent necessarily open or known to the network.

We can ssh between them or write scripts to have them communicate.

If we run env | more on the "mytestcontainer1" we see the following

[root@41f4f8e50eac /]# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:AC:11:00:02 
 inet addr: Bcast: Mask:
 inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
 RX packets:8 errors:0 dropped:0 overruns:0 frame:0
 TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0 
 RX bytes:648 (648.0 b) TX bytes:648 (648.0 b)

[root@41f4f8e50eac /]# env | more

Notice that the containers mytestcontainer1's ip is however it can see the web server running on port 80 at "mywebserver" at


Lecture: Taking Control of Ports

Previous videos have covered very basic port redirection and management. We will now discover why basic port to port redirection is inefficient as well as how to dynamically allocate host port redirects to known container ports. Finally, we will talk about how to bind a port to a single interface or IP rather than all network interfaces.

As we saw before you forward a port to a container using the -p option.Navigating yo the host OS ip will show the apache site(as long as apache is running on the set container_

docker run -itd -p 80:80 --name Mywebserver2 test:html /bin/bash

The following command will choose a random port in the range of 32768 and above and point it to the running ports on the container

docker run -itd -P --name Mywebserver3 test:html /bin/bash

If we do a docker ps we can see that port 32768 from the host OS now points to port 8o on our container

docker ps
489a53678edf test:html "/bin/bash" 2 minutes ago Up 2 minutes>80/tcp Mywebserver3

we can start another two servers call them Mywebserver4 ,5 .As can be seen two other random ip's have been assigned.

docker ps
7ba29fa87c00 test:html "/bin/bash" 3 seconds ago Up 2 seconds>80/tcp Mywebserver5
1f081a7ee14b test:html "/bin/bash" 11 seconds ago Up 10 seconds>80/tcp Mywebserver4
489a53678edf test:html "/bin/bash" 8 minutes ago Up 8 minutes>80/tcp Mywebserver3

We can also map specific ip's to port.this is usefull if we have more that one ip on our host machine.So we can say for ip on the host , forward port 5000 to port 80 on the container

docker run -itd -p --name Mywebserver6 test:html /bin/bash


If we want to forard for a specific ip choosing a random port we can use the following ::, In the example bellow i am choosing a random port to forard to port 80. This will only be visible on the host OS since we are using

docker run -itd -p --name Mywebserver7 test:html /bin/bash

The docke ps command result for the previous two examples

1c72ed451c56        test:html           "/bin/bash"         4 seconds ago       Up 3 seconds>80/tcp     Mywebserver7
d0d59f35d742        test:html           "/bin/bash"         6 minutes ago       Up 6 minutes>80/tcp   Mywebserver6


Lecture: Five Useful Docker CLI Commands

Now that we have the context to understand why these commands are meaningful and how the information is derived behind the scenes, its time to learn about some of the most useful and more advanced CLI utilities from Docker: * docker cp * docker diff * docker events * docker history * docker exec


Copy is usefull for copying files from a container.

Even if we can start a container and then stop it , as long as we know its name we can copy a file from that container instance using the following syntax, will copy the file test/me to the tmp directory

docker cp distracted_keller:/srv/test.me /tmp/



Can be usefull to see what files have changed, modified , added, deleted in a container since it was started

docker diff Mywebserver2
C /var
C /var/lock
C /var/lock/subsys
C /var/lock/subsys/httpd
C /var/run
C /var/run/httpd
C /var/run/httpd/httpd.pid
C /var/log
C /var/log/httpd
C /var/log/httpd/access_log
C /var/log/httpd/error_log



This will show events that happen to docker in general. i.e the system messages that are issued when a container is running

The example below shows what will be displayed while we execute docker events and we start a container

 docker events
2016-05-07T17:53:49.512603183-04:00 container create 2f65a4d528b4345922530f7c5b970b1c2233a5783e6a0676eca5b863c043526d (build-date=2016-03-31, image=centos:centos6, license=GPLv2, name=evil_khorana, vendor=CentOS)
2016-05-07T17:53:49.514070794-04:00 container attach 2f65a4d528b4345922530f7c5b970b1c2233a5783e6a0676eca5b863c043526d (build-date=2016-03-31, image=centos:centos6, license=GPLv2, name=evil_khorana, vendor=CentOS)
2016-05-07T17:53:49.598431754-04:00 network connect fd2407fc878a0442cf2fd1554032e4d2dad97b39f54150d29089b6bf68250d0b (container=2f65a4d528b4345922530f7c5b970b1c2233a5783e6a0676eca5b863c043526d, name=bridge, type=bridge)
2016-05-07T17:53:49.728383410-04:00 container start 2f65a4d528b4345922530f7c5b970b1c2233a5783e6a0676eca5b863c043526d (build-date=2016-03-31, image=centos:centos6, license=GPLv2, name=evil_khorana, vendor=CentOS)
2016-05-07T17:53:49.731207866-04:00 container resize 2f65a4d528b4345922530f7c5b970b1c2233a5783e6a0676eca5b863c043526d (build-date=2016-03-31, height=24, image=centos:centos6, license=GPLv2, name=evil_khorana, vendor=CentOS, width=80)

We can also pass a parameter and see all the events that happened from a s specific date

docker events --since '2016-05-07'



Has to do with the initial image history on which the containers are based on

So below we run history on test:html image and its almost like a revision history of what was done to that image

docker history test:html
1e097b024b70 About an hour ago /bin/bash 2.377 MB 
d34231955c88 About an hour ago /bin/bash 113.4 MB 
730e619a41ca 2 days ago /bin/sh -c #(nop) ADD file:06caba9b4b7649dba1 57 B 
8691adf7aca2 2 days ago /bin/sh -c #(nop) EXPOSE 80/tcp 0 B 
914df3ae6392 6 days ago /bin/sh -c #(nop) MAINTAINER stelios <stelios 0 B 
fc73b108c5ae 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B 
<missing> 5 weeks ago /bin/sh -c #(nop) LABEL name=CentOS Base Imag 0 B 
<missing> 5 weeks ago /bin/sh -c #(nop) ADD file:ae8f506cbd1f016c67 228.9 MB 
<missing> 8 months ago /bin/sh -c #(nop) MAINTAINER The CentOS Proje 0 B


We can execute a command without attaching to a container and get all the feedback from terminal on whats happening tonthe container when we execute the command

so we start a container and then we use the exec option to run update on that container

docker run -itd --name testexec centos:centos6 /bin/bash
docker exec -it testexec /usr/bin/yum -y update


Lecture: More Useful Docker CLI Commands

Now that we have the context to understand why these commands are meaningful and how the information is derived behind the scenes, its time to learn about some of the most useful and more advanced CLI utilities from Docker: * docker info * docker kill * docker save/export * docker load/import * docker pause/unpause * docker top


The docker info command gives us a general overview of the docker server :

docker info
Containers: 44
 Running: 3
 Paused: 0
 Stopped: 41
Images: 24
Server Version: 1.11.1
Storage Driver: devicemapper
 Pool Name: docker-253:0-370564-pool
 Pool Blocksize: 65.54 kB
 Base Device Size: 10.74 GB
 Backing Filesystem: xfs
 Data file: /dev/loop0
 Metadata file: /dev/loop1
 Data Space Used: 2.402 GB
 Data Space Total: 107.4 GB
 Data Space Available: 27 GB
 Metadata Space Used: 7.877 MB
 Metadata Space Total: 2.147 GB
 Metadata Space Available: 2.14 GB
 Udev Sync Supported: true
 Deferred Removal Enabled: false
 Deferred Deletion Enabled: false
 Deferred Deleted Device Count: 0
 Data loop file: /var/lib/docker/devicemapper/devicemapper/data
 Library Version: 1.02.107-RHEL7 (2015-12-01)
Logging Driver: json-file
Cgroup Driver: cgroupfs
 Volume: local
 Network: host bridge null
Kernel Version: 3.10.0-327.13.1.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux


Using "docker top" is like running top within the container , only we can do it from the host os. In the example below we run top for running container ourWeb1 , which is running apache.


root@localhost ~]# docker top ourWeb1
root 529 516 0 16:04 pts/2 00:00:00 /bin/bash
root 570 529 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 572 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 573 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 574 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 575 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 576 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 577 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 578 570 0 16:04 ? 00:00:00 /usr/sbin/httpd
48 579 570 0 16:04 ? 00:00:00 /usr/sbin/httpd


used in case a container is unresponsive , wont stop because eit maybe waiting for a system process, or due to any other issue.

Its an unclean way of stoppinga container li

docker kill ourWeb1


pausing a container is invisible to teh container itself

docker pause ourWeb1

to unpause issue the following

docker unpause ourWeb1


docker save/export docker load/import

We can export a container so that is can be used as a base image on another docker server.

First we need to stop the docker instance and then simply use the export command and output the command to a .tar file

docker stop ourWeb1
docker export ourWeb1 > /srv/ourweb.tar

To import the image we can simply run the following command

docker load -i /srv/ourweb.tar

also the following will work

docker load < /srv/ourweb.tar


Lecture: Optimizing Our Dockerfile Builds

Now that we have some background with our Dockerfile, let's talk about how to optimize a few things. We will demonstrate building a basic apache server with ssh

Firstly we modify the /root/dockerfile to conatin the following information

FROM centos:centos6
#start with this base image if it doesnt exist it will download it
MAINTAINER stelios <stelios@milidonis.com>
RUN yum -y update

RUN yum -y install httpd #install the apache service
RUN echo "/sbin/service httpd start" >> /root/.bashrc # to autostart apache

RUN yum -y install openssh-server #install ssh server
RUN echo "/sbin/service sshd start" >>/root/.bashrc # to autostart ssh

RUN echo "The system configuration is ended" > /root/README

EXPOSE 80 22

Then we build the image

docker build -t mytestnode .

The docker file runs different commands sequentially to build the docker image, and creates it takes more time and creates multiple container by the time it finishes, we can do it using one command by joining the commands using && so it is less time consuming and takes up less resources/ Its important that the command is on one line .

FROM centos:centos6
MAINTAINER stelios <stelios@milidonis.com>
RUN yum -y update && RUN yum -y install httpd #install the apache service &&
RUN echo "/sbin/service httpd start" >> /root/.bashrc && RUN yum -y install openssh-server && 
RUN echo "/sbin/service sshd start" >>/root/.bashrc && RUN echo "The system configuration is ended" > /root/README && EXPOSE 80 22