XIV.
Dockers
1. Applications Era
In today’s world, we are all surrounded by apps and websites. We use our smartphones and
computers to browse around internet and use all the web services through our mobile apps or
browsers. All these millions of web based data is coming somewhere far from some computers
which would be located in some datacenter. We generally call them servers; these servers could be
those physical machines that we see racked up in a datacenter with all those flashing lights and
cables.
If we take some examples like Amazon, Google, Netflix, Goibibo etc, all these businesses are
running on applications or we can say their applications are their business. This makes a very
important point that we cannot separate their business with their application.
Application needs compute resource to run and that comes from the server where they hosted their
application. In olden days when we did not have any virtualization or cloud computing we use to
run them directly on a physical server.
So, if I want to host an application on 10 webservers, I need ten physical servers under load
balancer serving the web traffic.
These servers are very expensive and we need to do lot of maintenance for them.
➢ We need to procure a server. A process where we place an order for the purchase.
➢ There is Capital expenditure or CapEx required.
➢ There is Operational expenditure (OpEx), like cooling, power, admins to maintain that
server farm.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
So, if I want to increase the capacity and add more servers I need to spend money and time on
above mentioned process. This is very common as business starts from very small user base and
then users/consumers traffic increases if business is doing well.
We deploy one application per server because we want our applications to be isolated. For example,
if we need web app, db app and few backend apps.
We may end up having multiple physical system each running a single instance of that app.
So, every time we need a new app to run we buy servers, install OS and setup our app on that.
And most of the time nobody knew the performance requirements of the new application!
This meant IT had to make guesses when choosing the model and size of
servers to buy.
As a result, IT did the only reasonable thing - it bought big fast servers with
lots of resiliency. After all, the last thing anyone wanted - including the
business - was under-powered servers.
Most part of the time these physical server compute resource will be under-utilized as low as 5-10%
of their potential capacity. A tragic waste of company capital and resources.
2. Virtualization Revolution.
VMware gave the world the virtual machine and everything changed after that. Now we could run
multiple applications isolated in separate OS but in the same physical server.
In the virtualization chapter, we discussed the benefits and features of virtualization, The
Hypervisor Architecture.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
3. Problems with Hypervisor Architecture.
Now we know that every VM has its own OS, which is a problem. OS needs fair amount of
resources like CPU, Memory, Storage etc. We also maintain OS licences and nurse them regularly
like patching, upgrades, config changes. We wanted to host an application but collected good
amount of fats over our infra, we are wasting OpEx and CapEx here. Think about shipping a vm
from one place to other place, this sounds a great idea that if we could bundle everything in a vm
image and ship it so the other person doesn’t need to setup vm from scratch can directly run the vm
from image. We did it in Vagrant chapter where we download preinstalled vm and have just run it.
But these images are heavy and bulky as they contain OS with the app. Booting them is a slow
process. So being portable it’s not convenient to ship the vm every time.
Shipping an application bundled with all the dependencies/libraries in an image without OS.
Hmm, sounds like we solved a big problem there. That’s what containers are.
Think about setting up an application in a vm or physical machine. We need OS setup,
dependencies, application deployed and some config changes in the OS. We follow a series of steps
to setup all these like setting up a LAMP stack. If we could bundle all these into one container and
ship it, then admins don’t need to do any setup on the target, all we need to do is pull a container
image and run it.
4. Containers.
If virtual machines are hardware virtualization then containers are OS virtualization. We don’t need
a real OS in the container to install our application. Applications inside the containers are dependent
on Host OS kernel where its running. So, if I have hosted java application like inside the container it
will use all the java libraries and config files from container data, but for compute resource its relied
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
on the Host OS kernel. Containers are like other processes that run in an Operating System but its
isolated, its processes, files, libraries, configurations are contained within the boundaries of the
container. Containers have their own process tree and networking also. Every container will have an
IP address and port on which the application inside container is running. This may sound like a
virtual machine but it’s not, remember VM has its own OS and containers does not.
Containers are very lightweight as it just has the libraries and application. So that means less
compute resource is utilized and that means more free space to run more container's. So, in terms of
resources also we are saving CapEx & OpEx.
Containers is not a modern technology, it was around us in different forms and technologies. But
Docker has brought it to a whole new level when it comes to building, shipping and managing
containers.
5. Dockers
Docker, Inc. started its life as a platform as a service (PaaS) provider called dotCloud. Behind the
scenes, the dotCloud platform leveraged Linux contain-ers. To help them create and manage these
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
containers they built an internal tool that they nick-named “Docker”. And that’s how Docker was
born!
In 2013 the dotCloud PaaS business was struggling and the company needed a new lease of life. To
help with this they hired Ben Golub as new CEO, rebranded the company as “Docker, Inc.”, got rid
of the dotCloud PaaS platform, and started a new journey with a mission to bring to Docker and
containers to the world.
Docker relies on Linux kernel features, such as namespaces and cgroups, to ensure resource
isolation and to package an application along with its dependencies. This packaging of the
dependencies enables an application to run as expected across different Linux operating systems.
It’s this portability that’s piqued the interest of developers and systems administrators alike.
But when somebody says “Docker” they can be referring to any of at least three things:
Docker, Inc. the company
Docker the container runtime and orchestration technology
3. Docker the open source project
When most of the people talk about Docker they generally refer to the Docker Engine.
Docker engine runs and orchestrate containers. As of now we can think docker engine like a
hypervisor. The same way as hypervisor technology that runs virtual machines, the Docker Engine
is the core container runtime that runs containers.
There are so many Docker technologies that gets integrated with the docker engine to automate,
orchestrate or manage docker containers.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
6. Installing Docker.
Docker can be installed on Windows, Mac and Linux OS.
We will install docker on Ubuntu 16.04 server in this tutorial.
Docker can be installed directly from Ubuntu repositories but that may not be the latest version of
Docker engine. To install the latest and greatest version, we will install it from official Docker
repository.
Uninstall old versions
Older versions of Docker were called docker or docker-engine. If these are installed,
uninstall them:
$ sudo apt-get remove docker docker-engine
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
It’s OK if apt-get reports that none of these packages are installed.
Add GPG key for Docker repository.
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Add the Docker repository
sudo add-apt-repository "deb [arch=amd64]
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Update the package
sudo apt-get update
Install Docker:
sudo apt-get install docker-ce -y
Docker should now be installed, the daemon started, and the process enabled to start on boot. Check
that it's running:
sudo systemctl status docker
Docker commands can be executed by root user or by providing sudo.
We can run docker command with normal user as well, to do it we need to add the user into the
docker group.
sudo usermod -aG docker <username>
You need to logout and login to reflect the changes.
Run Docker command to check if it’s working.
docker --version
When you install docker engine you get two components.
➢ Docker Client
➢ Docker Engine
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
7. Docker Engine’s Big Picture
Let’s quickly feel and taste the docker engine before we dive deep into it.
Broadly there are two areas where we operate in docker engines.
➢ Docker Images
➢ Docker containers
Images
As of now you can think images as vagrant boxes. It’s very much different from the vm images but
it will feel as same initially. Vagrant boxes are stopped state of a VM and Images and stopped state
of containers.
Run docker images command.
$ docker images
This command will list the downloaded images on your machine, so you won’t see anything now in
the output. We need to download some images, in docker world we call it Pulling an image.
So where does it pull the image from? Again, same analogy as vagrant boxes. We download the
vagrant boxes from vagrant cloud, docker images are downloaded from Docker Registries, the
most famous docker registry is DockerHub. There are other registries as well, from google, redhat
etc.
$ docker pull ubuntu:latest
latest: Pulling from library/ubuntu
bd97b43c27e3: Pull complete
6960dc1aba18: Pull complete
2b61829b0db5: Pull complete
1f88dc826b14: Pull complete
73b3859b1e43: Pull complete
Digest: sha256:ea1d854d38be82f54d39efe2c67000bed1b03348bcc2f3dc094f260855dff368
Status: Downloaded newer image for ubuntu:latest
Run the docker images command again to see the ubuntu:latest image you just pulled.
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 7b9b13f7b9c0 2 weeks ago 118MB
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
We’ll get into the details of where the image is stored and what’s inside of it in the next chapter. For
now, it’s enough to understand that it contains enough of an operating system (OS), as well as all
the code to run whatever application it’s designed for. The ubuntu image that we’ve pulled has a
stripped-down version of the Ubuntu Linux OS including a few of the common Ubuntu utilities.
Containers
Now that we have an image pulled locally on our Docker host, we can use the docker run command
to launch a container from it.
imran@DevOps:~$ docker run -it ubuntu:latest /bin/bash
root@b8765d3a67a9:/#
Look closely at the output form the command above. You should notice that your shell prompt has
changed. This is because your shell is now attached to the shell of the new container - you are
literally inside of the new container!
Let’s examine that docker run command.
➢ docker run tells the Docker daemon to start a new container.
➢ The -it flags tell the daemon to make the container interactive and to attach our current shell
to the shell of the container.
➢ Next, the command tells Docker that we want the container to be based on the ubuntu:latest
image.
➢ We tell it to run the /bin/bash process inside the container.
Run the following ps command from inside of the container to list all running processes.
root@b8765d3a67a9:/# ps -elf
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
4 S root 1 0 0 80 0 - 4560 wait 19:46 ? 00:00:00 /bin/bash
0 R root 10 1 0 80 0 - 8606 - 19:50 ? 00:00:00 ps -elf
As you can see from the output of the ps command, there are only two processes running inside of
the container:
➢ PID 1. This is the/bin/bash process that we told the container to run with the docker run command.
➢ PID 10. This is the ps elf process that we ran to list the running processes.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
The presence of the ps -elf process in the output above could be a bit misleading as it is a short-
lived process that dies as soon as the ps command exits. This means that the only long-running
process inside of the container is the /bin/bash process.
Press Ctrl-PQ to exit the container. This will land you back in the shell of your Docker host. You
can verify this by looking at your shell prompt.
In a previous step you pressed Ctrl-PQ to exit your shell from the container. Doing this from inside
of a container will exit you form the container without killing it. You can see all the running
containers on your system using the docker ps command.
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
b8765d3a67a9 ubuntu:latest "/bin/bash" 6 minutes ago Up 6 minutes
inspiring_heyrovsky
The output above shows a single running container. This is the container that you created earlier.
The presence of your container in this output
proves that it’s still running. You can also see that it was created 6 minutes ago and has been
running for 6 minutes.
Attaching to running containers
You can attach your shell to running containers with the docker exec command. As the container
from the previous steps are still running let’s connect back to it.
Note: The example below references a container called “inspiring_heyrovsky”. The name of your
container will be different, so remember to substitute “inspiring_heyrovsky” with the name or ID of
the container running on your Docker host.
imran@DevOps:~$ docker exec -it inspiring_heyrovsky /bin/bash
root@b8765d3a67a9:/#
Notice that your shell prompt has changed again. You are back inside the container.
The format of the docker exec command is:
docker exec -options <container-name or container-id> <command>.
In our example, we used the -it options to attach our shell to the container’s shell. We referenced the
container by name and told it to run the bash shell.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Exit the container again by pressing Ctrl-PQ.
Your shell prompt should be back to your Docker host.
Run the docker ps command again to verify that your container is still running.
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
b8765d3a67a9 ubuntu:latest "/bin/bash" 13 minutes ago Up 13 minutes
inspiring_heyrovsky
Stop the container and kill it using the docker stop and docker rm commands.
imran@DevOps:~$ docker stop inspiring_heyrovsky
inspiring_heyrovsky
imran@DevOps:~$ docker rm inspiring_heyrovsky
inspiring_heyrovsky
Verify that the container was successfully deleted by running another docker ps command.
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
imran@DevOps:~$
Now you would have got the taste of docker images and containers. We pulled an image, executed a
container, stopped and removed it. In next section, we will dig more in detail of images and then
containers.
8. Images
We have seen very basic stuff of docker images, now we will do a deep dive into docker images.
Images are built and distributed like software. As we have seen in Continuous Integration chapter
that there should be a process of Build & Release a software, we must do the same if we are
releasing Images.
We have mentioned earlier Images are stopped state of container so you can stop a container and
create a new image from it.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
We
see
fro
m
abo
ve
figu
re that we pull an image, run a container, customize it as per our requiretment, commit the container
into an image and then ship it.
However, once you’ve started a container form an image, the two constructs become dependent on
each other and you cannot delete the image until the last container using it has been stopped and
destroyed. Attempting to delete an image without stopping and destroying all containers using it
will result in errors.
Images that we are shipping should be light weight and should only contain the files and libraries
that required to run the application inside it. For example, if we are shipping a java application, it
should contain only java libraries, application server like tomcat and files to run our app and not
anything extra.
Pulling Images.
imran@DevOps:~$ docker pull node:latest
latest: Pulling from library/node
ef0380f84d05: Pull complete
24c170465c65: Pull complete
4f38f9d5c3c0: Pull complete
4125326b53d8: Pull complete
a1468c06f443: Pull complete
cb113e1791ca: Pull complete
519ce9303f95: Pull complete
f15f31d0549a: Pull complete
Digest: sha256:1d496e5c8e692dfabeb1cc8a18f01e2b501111f32c3d08e94e5402daeceb94e6
Status: Downloaded newer image for node:latest
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node latest f3068bc71556 27 hours ago 667MB
ubuntu latest 7b9b13f7b9c0 2 weeks ago 118MB
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
As you can see now we have two images downloaded on our docker engine.
Image registries
Docker images are stored in image registries. The most common image registry is Docker Hub.
Other registries exist including 3rd party registries and secure on-premises registries, but Docker
Hub is the default, and it’s the one we’ll use in this tutorial.
https://hub.docker.com/
Image registries contain multiple image repositories. Image repositories contain images. That might
be a bit confusing, so Figure 5.2 shows a picture of an image registry containing 3 repositories, and
each repository contains a few images.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Docker hub contains Official and unofficial repositories.
Official repositories are from Docker, Inc. These are safe and secure images with latest up to date
software.
Unofficial repositories are uploaded by anyone and are not verified by Docker, Inc.
The list below contains a few of the official repositories and shows their URLs that exist at the top
level of the Docker Hub namespace:
• nginx - https://hub.docker.com/_/nginx/
• busybox - https://hub.docker.com/_/busybox/
• redis - https://hub.docker.com/_/redis/
• mongo - https://hub.docker.com/_/mongo/
Our personal images live in the unofficial repositories. Below are some examples of images in my
repositories:
visualpath/myjsonsinatra - https://hub.docker.com/r/visualpath/myjsonsinatra/
visualpath/devops-docker-ci - https://hub.docker.com/r/visualpath/devops-docker-ci/
Image Tags.
While pulling a image we give the imagename:TAG and docker will reach by default to dockerhub
registry and find the image with the TAG we specified.
docker pull nginx:latest
Tag generally refers to the version of the image from the repository.
If we are looking for some other version like 1.12.0 then we can use below command.
docker pull nginx:1.12.0
If we do not specify any tag then the default tag is latest. Latest tag does not mean that the images is
latest in version, it’s just the name of the tag and that’s all.
docker pull nginx
Above command will download the nginx image with latest tag.
Images and layers
All Docker images are made up of one or more read-only layers as shown below.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
There are a few ways to see and inspect the layers that make up an image,
and we’ve already seen one of them. Let’s take a second look at the output of the docker
pull node:latest command from earlier:
$ docker pull node
Using default tag: latest
latest: Pulling from library/node
ef0380f84d05: Pull complete
24c170465c65: Pull complete
4f38f9d5c3c0: Pull complete
4125326b53d8: Pull complete
a1468c06f443: Pull complete
cb113e1791ca: Pull complete
519ce9303f95: Pull complete
f15f31d0549a: Pull complete
Digest: sha256:1d496e5c8e692dfabeb1cc8a18f01e2b501111f32c3d08e94e5402daeceb94e6
Each line in the output above that ends with “Pull complete” represents a layer in the image that
was pulled. As we can see, this image has 5 layers.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Each layer is only a set of differences from the layer before it. The layers are stacked on top of each
other. When you create a new container, you add a new writable layer on top of the underlying
layers. This layer is often called the “container layer”. All changes made to the running container,
such as writing new files, modifying existing files, and deleting files, are written to this thin
writable container layer. The diagram below shows a container based on the Ubuntu 15.04 image.
Container and layers
The major difference between a container and an image is the top writable layer. All writes to the
container that add new or modify existing data are stored in this writable layer. When the container
is deleted, the writable layer is also deleted. The underlying image remains unchanged.
Because each container has its own writable container layer, and all changes are stored in this
container layer, multiple containers can share access to the same underlying image and yet have
their own data state. The diagram below shows multiple containers sharing the same Ubuntu 15.04
image.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Docker uses storage drivers to manage the contents of the image layers and the writable container
layer. Each storage driver handles the implementation differently, but all drivers use stackable
image layers and the copy-on-write (CoW) strategy.
Another way to see the layers that make up an image is to inspect the
image with the docker inspect command. The example below inspects the same ubuntu:latest
image.
$ docker inspect node
"Id": "sha256:f3068bc71556e181c774ee7dadc4d3ebbf5643e95680a202779f08146332547d",
"RepoTags": [
"node:latest"
],
"RepoDigests": [
"node@sha256:1d496e5c8e692dfabeb1cc8a18f01e2b501111f32c3d08e94e5402daeceb94e6"
],
"Parent": "",
"Comment": "",
"Created": "2017-06-15T17:26:33.424702587Z",
"Container": "8c6ffc2b7a445e6f2ade22c6be3a430c772e0ab61bf0ee4fff69b36a24e9123e",
"ContainerConfig": {
"Hostname": "5c84359661e5",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NPM_CONFIG_LOGLEVEL=info",
"NODE_VERSION=8.1.2",
"YARN_VERSION=0.24.6"
],
"Cmd": [
"/bin/sh",
"-c",
"#(nop) ",
"CMD [\"node\"]"
],
"ArgsEscaped": true,
"Image": "sha256:3864d82628abf07bbdebe3d1d529aa90eef89f8dc99d06dea2a35329879c81a7",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {}
},
"DockerVersion": "17.03.1-ce",
"Author": "",
"Config": {
"Hostname": "5c84359661e5",
"Domainname": "",
"User": "",
"AttachStdin": false,
"AttachStdout": false,
"AttachStderr": false,
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"NPM_CONFIG_LOGLEVEL=info",
"NODE_VERSION=8.1.2",
"YARN_VERSION=0.24.6"
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
],
"Cmd": [
"node"
],
"ArgsEscaped": true,
"Image": "sha256:3864d82628abf07bbdebe3d1d529aa90eef89f8dc99d06dea2a35329879c81a7",
"Volumes": null,
"WorkingDir": "",
"Entrypoint": null,
"OnBuild": [],
"Labels": {}
},
"Architecture": "amd64",
"Os": "linux",
"Size": 666628404,
"VirtualSize": 666628404,
"GraphDriver": {
"Data": null,
"Name": "aufs"
},
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:007ab444b234be691d8dafd51839b7713324a261b16e2487bf4a3f989ded912d",
"sha256:4902b007e6a712835de8e09c385c0f061638323c3cacc13f7190676f05dad9d7",
"sha256:bb07d0c1008de4fd468f865764e6f1129ba53f4bfe6ab14dd5eb3ab256947ab0",
"sha256:ecf5c2e2468e7fe6600193972ffc659214050d8829f44e5194a22997de13aab4",
"sha256:7b3b4fef39c1df95f7a015716bc980dad38fff92ebba6de82d5add10b1258523",
"sha256:677f02386f077da16bfbe00af5305928545c11c40dccf70f93fa332f617c1fba",
"sha256:99c62c5bb4f21ab5b288339ce1a29e33cb3a82670ec1a9254730b6925d7da7dc",
"sha256:0dd4309d61fe600b230931ce669a93ee0baf9b2c18f574749c3af1e3eed44b83"
Deleting Images
When you no longer need an image, you can delete it form your Docker host with the docker rmi
command. rmi is short for remove image.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Delete the node image pulled in the previous step with the docker rmi command. The example
below addresses the image by its ID.
$ docker rmi f3068bc71556
9. Containers
Container is the runtime instance of an image like we start a vm from vagrant box. We can start
multiple containers from one single image.
We create container from an image by giving docker run command. Containers run until the
processes running inside them exists. There should be minimum one process running inside the
container with PID 1. If this process dies the containers also dies.
imran@DevOps:~$ docker run -it ubuntu:latest /bin/bash
root@ae141c80e436:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 2 21:44 ? 00:00:00 /bin/bash
root 11 1 0 21:44 ? 00:00:00 ps -ef
In above container /bin/bash has the PID 1, this process will get killed if we hit exit command.
root@ae141c80e436:/# exit
exit
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
As exit will logout and kill the current shell and that’s our PID 1 our container also got killed with
it.
docker ps -a will show all the containers running or exited.
imran@DevOps:~$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
ae141c80e436 ubuntu:latest "/bin/bash" 12 minutes ago Exited (0) 10
minutes ago zen_bell
159b1586b69b ubuntu:latest "/bin/bash" 12 minutes ago Exited (0) 12
minutes ago hungry_noether
We can start a exited container by giving docker start <containerid>
imran@DevOps:~$ docker start ae141c80e436
ae141c80e436
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
ae141c80e436 ubuntu:latest "/bin/bash" 14 minutes ago Up 3 seconds
zen_bell
docker stop will stop a running container.
imran@DevOps:~$ docker stop ae141c80e436
ae141c80e436
docker rm will remove the container with its data.
imran@DevOps:~$ docker rm ae141c80e436
ae141c80e436
Running a webservice in a container.
imran@DevOps:~$ docker run -d --name newwebserver -p 8070:80 visualpath/devops-
docker-ci
c695f224adf6a91f971018c6934b255e5cb86d6d8f6a4445d24fa7d7f1f70967
We started the above container in backgroud by option -d
we also have given name to our container by --name option
Above image is an apache webservice which is running on port 80 but can be accessed by
forwarded port from host. Host Port 8070 is mapped to containers port 80. That means if we access
host machines IP on port 8070 we will get service running on port 80 from the containers.
Containers are not directly accessed by their IP’s because container Ip’s are not permanent. We will
discuss that in detail in networking section. We access service running in container from host port
which are redirected to containers port this is called a port forwarding.
-p 8070:80 means host port 8070 is mapped to containers port 80.
Verify the container webservice by accessing it from browser on http://hostip:8070
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Check nginx, apache and Jenkins registries from dockerhub and run them to understand more about
it.
$ docker run -p 8080:8080 -p 50000:50000 -v /your/home:/var/jenkins_home Jenkins
Here we are mapping two ports 8080 and 50000, host and container ports are same which is ok if
your host ports are not busy.
Containers data is not persistent that means if we delete the container its data is also lost, which is
obvious. But if we want to keep that data safe on host machine, we can use -v flag which is for
volumes. Left hand side is host machine directory path and right-hand side is containers directory
path which you want to save on host machine. It’s similar to our vagrant sync directories.
Now even if we delete the container its data in /var/jenkins_home will be safe on the host machine
in /your/home directory.
Inspecting Containers
In the previous example you might have noticed that we didn’t specify a command for the container
when we issued the docker run. Yet the container ran a simple web service. How did this happen?
When building a Docker image, it’s possible to embed a default command or process you want
containers using the image to run. If we run a docker inspect command against the image we used
to run our container, we’ll be able to see the command/process that the container will run when it
starts.
imran@DevOps:~$ docker inspect c695f224adf6a91f971018c6934b255e5cb86d6d8f6a4445d24fa7d7f1f70967
"Id": "c695f224adf6a91f971018c6934b255e5cb86d6d8f6a4445d24fa7d7f1f70967",
"Created": "2017-06-16T22:13:41.841190294Z",
"Path": "/bin/sh",
"Args": [
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
"-c",
"/usr/sbin/apache2ctl -D FOREGROUND"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 17026,
"ExitCode": 0,
"Error": "",
"StartedAt": "2017-06-16T22:13:42.656496753Z",
"FinishedAt": "0001-01-01T00:00:00Z"
10. Building & Shipping Images
Docker can build images automatically by reading the instructions from a Dockerfile, a text file that
contains all the commands, in order, needed to build a given image. Dockerfiles adhere to a specific
format and use a specific set of instructions.
Dockerfile will define what goes on in the environment inside your container. Access to resources like
networking interfaces and disk drives is virtualized inside this environment, which is isolated from the
rest of your system, so you have to map ports to the outside world, and be specific about what files you
want to “copy in” to that environment. However, after doing that, you can expect that the build of your
app defined in thisDockerfile will behave exactly the same wherever it runs.
Dockerfile
Create an empty directory and put this file in it, with the name Dockerfile. Take note of the comments
that explain each statement.
# Use an official Python runtime as a base image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
ADD . /app
# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
This Dockerfile refers to a couple of things we haven’t created yet, namely app.py and
requirements.txt. Let’s get those in place next.
The app itself
Grab these two files and place them in the same folder as Dockerfile. This completes our app, which as
you can see is quite simple. When the above Dockerfile is built into an image, app.py and
requirements.txtwill be present because of that Dockerfile’s ADD command, and the output from app.py will
be accessible over HTTP thanks to the EXPOSE command.
requirements.txt
Flask
Redis
app.py
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
Now we see that pip install -r requirements.txt installs the Flask and Redis libraries for Python, and the app
prints the environment variable NAME, as well as the output of a call to socket.gethostname(). Finally,
because Redis isn’t running (as we’ve only installed the Python library, and not Redis itself), we should
expect that the attempt to use it here will fail and produce the error message.
Note: Accessing the name of the host when inside a container retrieves the container ID,
which is like the process ID for a running executable.
Build the app
That’s it! You don’t need Python or anything in requirements.txt on your system, nor will building or
running this image install them on your system. It doesn’t seem like you’ve really set up an environment
with Python and Flask, but you have.
Here’s what ls should show:
$ ls
Dockerfile app.py requirements.txt
Now run the build command. This creates a Docker image, which we’re going to tag using -t so it has a
friendly name.
docker build -t friendlyhello .
Where is your built image? It’s in your machine’s local Docker image registry:
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
$ docker images
REPOSITORY TAG IMAGE ID
friendlyhello latest 326387cea398
Run the app
Run the app, mapping your machine’s port 4000 to the container’s EXPOSEd port 80 using -p:
docker run -p 4000:80 friendlyhello
You should see a notice that Python is serving your app at http://0.0.0.0:80. But that message is coming
from inside the container, which doesn’t know you mapped port 80 of that container to 4000, making
the correct URL http://localhost:4000.
Go to that URL in a web browser to see the display content served up on a web page, including
“Hello World” text, the container ID, and the Redis error message.
You can also use the curl command in a shell to view the same content.
$ curl http://localhost:4000
<h3>Hello World!</h3><b>Hostname:</b> 8fc990912a14<br/><b>Visits:</b> <i>cannot connect to Redis, counter
disabled</i>
Note: This port remapping of 4000:80 is to demonstrate the difference between what you
EXPOSEwithin the Dockerfile, and what you publish using docker run -p. In later steps, we’ll
just map port 80 on the host to port 80 in the container and use http://localhost.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Hit CTRL+C in your terminal to quit.
Now let’s run the app in the background, in detached mode:
docker run -d -p 4000:80 friendlyhello
You get the long container ID for your app and then are kicked back to your terminal. Your container is
running in the background. You can also see the abbreviated container ID with docker ps (and both work
interchangeably when running commands):
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
1fa4ab2cf395 friendlyhello "python app.py" 28 seconds ago
You’ll see that CONTAINER ID matches what’s on http://localhost:4000.
Now use docker stop to end the process, using the CONTAINER ID, like so:
docker stop 1fa4ab2cf395
Share your image
To demonstrate the portability of what we just created, let’s upload our built image and run it
somewhere else. After all, you’ll need to learn how to push to registries when you want to deploy
containers to production.
A registry is a collection of repositories, and a repository is a collection of images—sort of like a
GitHub repository, except the code is already built. An account on a registry can create many
repositories. The dockerCLI uses Docker’s public registry by default.
Note: We’ll be using Docker’s public registry here just because it’s free and pre-configured,
but there are many public ones to choose from, and you can even set up your own private
registry using Docker Trusted Registry.
Log in with your Docker ID
If you don’t have a Docker account, sign up for one at cloud.docker.com. Make note of your
username.
Log in to the Docker public registry on your local machine.
docker login
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Tag the image
The notation for associating a local image with a repository on a registry is username/repository:tag. The
tag is optional, but recommended, since it is the mechanism that registries use to give Docker images a
version. Give the repository and tag meaningful names for the context, such as get-started:part1. This will
put the image in the get-started repository and tag it as part1.
Now, put it all together to tag the image. Run docker tag image with your username, repository, and tag
names so that the image will upload to your desired destination. The syntax of the command is:
docker tag image username/repository:tag
For example:
docker tag friendlyhello john/get-started:part1
Run docker images to see your newly tagged image. (You can also use docker image ls.)
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
friendlyhello latest d9e555c53008 3 minutes ago 195MB
john/get-started part1 d9e555c53008 3 minutes ago 195MB
python 2.7-slim 1c7128a655f6 5 days ago 183MB
...
Publish the image
Upload your tagged image to the repository:
docker push username/repository:tag
Once complete, the results of this upload are publicly available. If you log in to Docker Hub, you will
see the new image there, with its pull command.
Pull and run the image from the remote repository
From now on, you can use docker run and run your app on any machine with this command:
docker run -p 4000:80 username/repository:tag
If the image isn’t available locally on the machine, Docker will pull it from the repository.
$ docker run -p 4000:80 john/get-started:part1
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Unable to find image 'john/get-started:part1' locally
part1: Pulling from orangesnap/get-started
10a267c67f42: Already exists
f68a39a6a5e4: Already exists
9beaffc0cf19: Already exists
3c1fe835fb6b: Already exists
4c9f1fa8fcb8: Already exists
ee7d8f576a14: Already exists
fbccdcced46e: Already exists
Digest: sha256:0601c866aab2adcc6498200efd0f754037e909e5fd42069adeff72d1e2439068
Status: Downloaded newer image for john/get-started:part1
* Running on http://0.0.0.0:80/ (Press CTRL+C to quit)
Note: If you don’t specify the :tag portion of these commands, the tag of :latest will be
assumed, both when you build and when you run images. Docker will use the last version of
the image that ran without a tag specified (not necessarily the most recent image).
No matter where docker run executes, it pulls your image, along with Python and all the dependencies
from requirements.txt, and runs your code. It all travels together in a neat little package, and the host
machine doesn’t have to install anything but Docker to run it.
Dockerfile Instructions
We have seen in previous section that Dockerfile is used to build docker images. It contains the list
of instructions that docker reads to setup an Image. There are around a dozen Instruction that we
can use in our Dockerfile.
1.ADD
2.CMD
3.ENTRYPOINT
4.ENV
5.EXPOSE
6.FROM
7.MAINTAINER
8.RUN
9.USER
10.VOLUME
11.WORKDIR
12.ONBUILD
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
FROM
This instruction is used to set the base image for subsequent instructions. It is mandatory to set this
in the first line of a Dockerfile. You can use it any number of times though.
Example:
FROM ubuntu:latest
MAINTAINER
This is a non-executable instruction used to indicate the author of the Dockerfile.
Example:
MAINTAINER <name>
RUN
This instruction lets you execute a command on top of an existing layer and create a new layer with
the results of command execution.
For example, if there is a pre-condition to install PHP before running an application, you can run
appropriate commands to install PHP on top of base image (say Ubuntu) like this:
FROM ubuntu
RUN apt-get update update apt-get install php5
CMD
The major difference between CMD and RUN is that CMD doesn’t execute anything during the build
time. It just specifies the intended command for the image. Whereas RUN executes the command
during build time.
Note: there can be only one CMD instruction in a Dockerfile, if you add more, only the last one takes
effect.
Example:
CMD "echo" "Hello World!"
EXPOSE
While running your service in the container you may want your container to listen on specified
ports. The EXPOSE instruction helps you do this.
Example:
EXPOSE 6456
ENV
This instruction can be used to set the environment variables in the container.
Example:
ENV var_home="/var/etc"
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
COPY
This instruction is used to copy files and directories from a specified source to a destination (in the
file system of the container).
Example:
COPY preconditions.txt /usr/temp
ADD
This instruction is similar to the COPY instruction with few added features like remote URL support
in the source field and local-only tar extraction. But if you don’t need an extra feature, it is
suggested to use COPY as it is more readable.
Example:
ADD http://www.site.com/downloads/sample.tar.xz /usr/src
ENTRYPOINT
You can use this instruction to set the primary command for the image.
For example, if you have installed only one application in your image and want it to run whenever
the image is executed, ENTRYPOINT is the instruction for you.
Note: arguments are optional, and you can pass them during the runtime with something like
docker run <image-name>.
Also, all the elements specified using CMD will be overridden, except the arguments. They will be
passed to the command specified in ENTRYPOINT.
Example:
CMD "Hello World!"
ENTRYPOINT echo
VOLUME
You can use the VOLUME instruction to enable access to a location on the host system from a
container. Just pass the path of the location to be accessed.
Example:
VOLUME /data
USER
This is used to set the UID (or username) to use when running the image.
Example:
USER daemon
WORKDIR
This is used to set the currently active directory for other instructions such as RUN, CMD,
ENTRYPOINT, COPY and ADD.
Note that if relative path is provided, the next WORKDIR instruction will take it as relative to the
path of previous WORKDIR instruction.
Example:
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
WORKDIR /user
WORKDIR home
RUN pwd
This will output the path as /user/home.
ONBUILD
This instruction adds a trigger instruction to be executed when the image is used as the base for
some other image. It behaves as if a RUN instruction is inserted immediately after the FROM
instruction of the downstream Dockerfile. This is typically helpful in cases where you need a static
base image with a dynamic config value that changes whenever a new image must be built (on top
of the base image).
Example:
ONBUILD RUN rm -rf /usr/temp
Dockerhub has Dockerfile for every official Image that’s hosted there.
Above screenshot is from nginx official repository from Dockerhub. If you see there are links to
Dockerfile for every version of the image. The links points to Dockerfile hosted in github.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
These Dockerfiles are the best place to learn the Dockerfile as its verified from Docker Inc.
One of the best practice is that we combine multiple commands in RUN instruction by using &&
Every RUN instruction creates layer on the images, so if you have ten RUN instruction that creates
ten extra layers in your image. To avoid this, we can right all the commands in single RUN
instruction by combining all the commands with && as shown in above screenshot.
A sample mongodb Dockerfile.
############################################################
# Dockerfile to build MongoDB container images
# Based on Ubuntu
############################################################
# Set the base image to Ubuntu
FROM ubuntu
# File Author / Maintainer
MAINTAINER Example McAuthor
# Update the repository sources list
RUN apt-get update
################## BEGIN INSTALLATION ######################
# Install MongoDB Following the Instructions at MongoDB Docs
# Ref: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu/
# Add the package verification key
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
# Add MongoDB to the repository sources list
RUN echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist
10gen' | tee /etc/apt/sources.list.d/mongodb.list
# Update the repository sources list once more
RUN apt-get update
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
# Install MongoDB package (.deb)
RUN apt-get install -y mongodb-10gen
# Create the default data directory
RUN mkdir -p /data/db
##################### INSTALLATION END #####################
# Expose the default port
EXPOSE 27017
# Default port to execute the entrypoint (MongoDB)
CMD ["--port 27017"]
# Set default container command
ENTRYPOINT usr/bin/mongod
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
11. Container Networking Basics
A simple, static web server
Run the Docker Hub image nginx, which contains a basic web server:
imran@DevOps:~$ docker run -d -P nginx
b53c99839ccf662b17ff96424352701cc494b788e4d97525d930406b0cfdb237
Docker will download the image from the Docker Hub.
-d tells Docker to run the image in the background.
-P tells Docker to make this service reachable from other computers.
(-P is the short version of --publish-all.)
But, how do we connect to our web server now?
Finding our web server port
We will use docker ps:
imran@DevOps:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES
b53c99839ccf nginx "nginx -g 'daemon ..." About a minute ago Up About a
minute 0.0.0.0:32769->80/tcp distracted_bassi
The web server is running on ports 80 and 443 inside the container.Those ports are mapped to
ports 32769 and 32768 on our Docker host.We will explain the whys and hows of this port
mapping.
But first, let's make sure that everything works properly.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Connecting to our web server (GUI)
Point your browser to the IP address of your Docker host, on the port shown by
docker ps for container port 80.
Connecting to our web server (CLI)
You can also use curl directly from the Docker host.
Make sure to use the right port number if it is different from the example below:
$ curl localhost:32769
<!DOCTYPE html> <html>
<head>
<title>Welcome to nginx!</title>
Why are we mapping ports?
We are out of IPv4 addresses. Containers cannot have public IPv4 addresses. They have private
addresses. Services have to be exposed port by port. Ports have to be mapped to avoid conflicts.
Finding the web server port in a script
Parsing the output of docker ps would be painful.There is a command to help us:
$ docker port <containerID>
80 32769
Manual allocation of port numbers
If you want to set port numbers yourself, no problem:
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
$ docker run -d -p 80:80 nginx
$ docker run -d -p 8000:80 nginx
$ docker run -d -p 8080:80 -p 8888:80 nginx
We are running two NGINX web servers. The first one is exposed on port 80.The second one is
exposed on port 8000.The third one is exposed on ports 8080 and 8888.Note: the convention is
port-on-host: port-on-container.
Plumbing containers into your infrastructure
There are many ways to integrate containers in your network. Start the container, letting Docker
allocate a public port for it. Then retrieve that port number and feed it to your configuration.
Pick a fixed port number in advance, when you generate your configuration. Then start your
container by setting the port numbers manually.
Use a network plugin, connecting your containers with e.g. VLANs, tunnels...
Enable Swarm Mode to deploy across a cluster.
The container will then be reachable through any node of the cluster.
Finding the container's IP address
We can use the docker inspect command to find the IP address of the container.
$ docker inspect --format '{{
.NetworkSettings.IPAddress }}' <yourContainerID> 172.17.0.3
docker inspect is an advanced command, that can retrieve a ton of information about our
containers. Here, we provide it with a format string to extract exactly the private IP address of the
container.
Pinging our container
We can test connectivity to the container using the IP address we've just discovered.
Let's see this now by using the ping tool.
$ ping <ipAddress>
64 bytes from <ipAddress>: icmp_req=1 ttl=64 time=0.085 ms 64 bytes from
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
The different network drivers
A container can use one of the following drivers:
bridge (default)
none
host
container
The driver is selected with docker run --net ....
The default bridge
By default, the container gets a virtual eth0 interface. (In addition to its own private lo loopback
interface.)
That interface is provided by a veth pair. It is connected to the Docker bridge.
(Named docker0 by default; configurable with --bridge.)
Addresses are allocated on a private, internal subnet.
(Docker uses 172.17.0.0/16 by default; configurable with –bip.)
Outbound traffic goes through an iptables MASQUERADE rule. Inbound traffic goes through an
iptables DNAT rule. The container can have its own routes, iptables rules, etc.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
12. The Container Network Model
The Container Network Model
The CNM was introduced in Engine 1.9.0 (November 2015).
The CNM adds the notion of a network, and a new top-level command to manipulate and see
those networks: docker network.
What's in a network?
• Conceptually, a network is a virtual switch.
• It can be local (to a single Engine) or global (across multiple hosts).
• A network has an IP subnet associated to it.
• A network is managed by a driver.
• A network can have a custom IPAM (IP allocator).
• Containers with explicit names are discoverable via DNS.
• All the drivers that we have seen before are available.
• A new multi-host driver, overlay, is available out of the box.
• More drivers can be provided by plugins (OVS, VLAN...)
Creating a network
Let's create a network called dev.
$ docker network create dev
27c06defdb9d99002e670935d8fbcd24ef7f24eb3fd1c22b18f383005722a3c4
The network is now visible with the network ls command:
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
d7dfc8dc0972 bridge bridge local
27c06defdb9d dev bridge local
708d4a2432fd host host local
0e356843766c none null local
Placing containers on a network
We will create a named container on this network. It will be reachable with its name, search.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
$ docker run -d --name search --net dev elasticsearch
aec474a67e5d12490f503a9ab209cd6074f0b7ddcb12ee783476b3476ad2764a
Communication between containers
Now, create another container on this network.
$ docker run -ti --net dev alpine sh
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
2aecc7e1714b: Pull complete
Digest:
sha256:0b94d1d1b5eb130dd0253374552445b39470653fb1a1ec2d81490948876e462c
Status: Downloaded newer image for alpine:latest
/ #
From this new container, we can resolve and ping the other one, using its assigned name:
/ # ping search
PING search (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.136 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.063 ms
64 bytes from 172.18.0.2: seq=2 ttl=64 time=0.092 ms
3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt
min/avg/max/mdev = 0.114/0.149/0.221/0.052 ms
root@0ecccdfa45ef:/#
Resolving container addresses
In Docker Engine 1.9, name resolution is implemented with /etc/hosts, and updating it each time
containers are added/removed.
[root@0ecccdfa45ef /]# cat /etc/hosts
.0ecccdfa45ef
.localhost
::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters
.search
.search.dev
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
In Docker Engine 1.10, this has been replaced by a dynamic resolver.
(This avoids race conditions when updating /etc/hosts.)
Connecting multiple containers together
Let's try to run an application that requires two containers.
The first container is a web server.
The other one is a redis data store.
We will place them both on the dev network created before.
Running the web server
10) The application is provided by the container image jpetazzo/ trainingwheels.
11) We don't know much about it so we will try to run it and see what happens!
Start the container, exposing all its ports:
$ docker run --net dev -d -P jpetazzo/trainingwheels
Check the port that has been allocated to it:
$ docker ps -l
Test the web server
If we connect to the application now, we will see an error page:
This is because the Redis service is not running.
This container tries to resolve the name redis.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Note: we're not using a FQDN or an IP address here; just redis.
Start the data store
✓ We need to start a Redis container.
✓ That container must be on the same network as the web server.
✓ It must have the right name (redis) so the application can find
it.
Start the container:
$ docker run --net dev --name redis -d redis
Test the web server again
If we connect to the application now, we should see that the app is working correctly:
When the app tries to resolve redis, instead of getting a DNS error, it gets the IP address
of our Redis container.
A few words on scope
What if we want to run multiple copies of our application?
Since names are unique, there can be only one container named redis at a time.
We can specify --net-alias to define network-scoped aliases, independently of the
container name.
Let's remove the redis container:
$ docker rm -f redis
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
And create one that doesn't block the redis name:
$ docker run --net dev --net-alias redis -d redis
Check that the app still works (but the counter is back to 1, since we wiped out the old Redis
container).
Names are local to each network
Let's try to ping our search container from another container, when that other container is not on
the dev network.
$ docker run --rm alpine ping search ping: bad address 'search'
Names can be resolved only when containers are on the same network. Containers can contact
each other only when they are on the same network (you can try to ping using the IP address to
verify).
Network aliases
We would like to have another network, prod, with its own search container. But there can be
only one container named search! We will use network aliases.
A container can have multiple network aliases. Network aliases are local to a given network
(only exist in this network). Multiple containers can have the same network alias (even on the
same network). In Docker Engine 1.11, resolving a network alias yields the IP addresses of all
containers holding this alias.
Creating containers on another network
Create the prod network.
$ docker create network prod
5a41562fecf2d8f115bedc16865f7336232a04268bdf2bd816aecca01b68d5 0c
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
We can now create multiple containers with the search alias on the new prod network.
$ docker run -d --name prod-es-1 --net-alias search --net prod elasticsearch
38079d21caf0c5533a391700d9e9e920724e89200083df73211081c8a356d771
$ docker run -d --name prod-es-2 --net-alias search --net prod elasticsearch
1820087a9c600f43159688050dcc164c298183e1d2e62d5694fd46b10ac3bc3d
Resolving network aliases
Let's try DNS resolution first, using the nslookup tool that ships with the alpine image.
$ docker run --net prod --rm alpine nslookup search Name: search
Address 1: 172.23.0.3 prod-es-2.prod Address 2: 172.23.0.2 prod-es-1.prod
(You can ignore the can't resolve '(null)' errors.)
Connecting to aliased containers
Each ElasticSearch instance has a name (generated when it is started). This name can be seen
when we issue a simple HTTP request on the ElasticSearch API endpoint.
Try the following command a few times:
$ docker run --rm --net dev centos curl -s search:9200
"name" : "Tarot",
...
Then try it a few times by replacing --net dev with --net prod:
$ docker run --rm --net prod centos curl -s search:9200
"name" : "The Symbiote",
...
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Good to know...
Docker will not create network names and aliases on the default bridge network.
Therefore, if you want to use those features, you have to create a custom network first.
Network aliases are not unique: you can give multiple containers the same alias on the same
network.
In Engine 1.10: one container will be selected and only its IP address will be returned when
resolving the network alias.
In Engine 1.11: when resolving the network alias, the DNS reply includes the IP addresses of all
containers with this network alias. This allows crude load balancing across multiple containers
(but is not a substitute for a real load balancer).
In Engine 1.12: enabling Swarm Mode gives access to clustering features, including an advanced
load balancer using Linux IPVS.
Creation of networks and network aliases is generally automated with tools likeCompose
(covered in a few chapters).
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
13. Local Development Workflow with Docker
Using a Docker container for local development
Never again:
• "Works on my machine"
• "Not the same version"
• "Missing dependency"
By using Docker containers, we will get a consistent development environment.
Our "namer" application
The code is available on https://github.com/jpetazzo/namer.
The image jpetazzo/namer is automatically built by the Docker Hub .
Let's run it with:
$ docker run -dP jpetazzo/namer
Check the port number with docker ps and open the application.
Let's look at the code
Let's download our application's source code.
$ git clone https://github.com/jpetazzo/namer
$ cd namer $ ls -1 company_name_generator.rbconfig.ru docker-compose.yml
Dockerfile Gemfile
Where's my code?
According to the Dockerfile, the code is copied into /src :
FROM ruby
MAINTAINER Education Team at Docker <education@docker.com>
COPY . /src
WORKDIR /src
RUN bundler install
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
CMD ["rackup", "--host", "0.0.0.0"]
EXPOSE 9292
We want to make changes inside the container without rebuilding it each time.
For that, we will use a volume.
Our first volume
We will tell Docker to map the current directory to /src in the container.
docker run -d -v $(pwd):/src -p 80:9292 jpetazzo/namer
The d flag indicates that the container should run in detached mode (in the background).
The v flag provides volume mounting inside containers.
The p flag maps port 9292 inside the container to port 80 on the host.
jpetazzo/namer is the name of the image we will run.
We don't need to give a command to run because the Dockerfile already specifies rackup.
Mounting volumes inside containers
The v flag mounts a directory from your host into your Docker container. The flag structure is:
[host-path]:[container-path]:[rw|ro]
✓ If [hostpath] or [containerpath] doesn't exist it is created.
✓ You can control the write status of the volume with the ro and rw
options.
✓ If you don't specify rw or ro, it will be rw by default.
There will be a full chapter about volumes!
Testing the development container
Now let us see if our new container is running.
$ docker ps
Viewing our application
Now let's browse to our web application on:
http://<yourHostIP>:80
We can see our company naming application.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Making a change to our application
Our customer really doesn't like the color of our text. Let's change it.
$ vi company_name_generator.rb
And change
color: royalblue;
To: color: red;
Refreshing our application
Now let's refresh our browser:
http://<yourHostIP>:80
We can see the updated color of our company naming application.
Improving the workflow with Compose
You can also start the container with the following command: $ dockercompose up d
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
This works thanks to the Compose file, dockercompose.yml:
www: build: . volumes:
.:/src
ports:
80:9292
Why Compose?
Specifying all those "docker run" parameters is tedious.
And errorprone.
We can "encode" those parameters in a "Compose file.
When you see a dockercompose.yml file, you know that you can use dockercompose up.
Compose can also deal with complex, multicontainer apps. (More on this later.)
Workflow explained
We can see a simple workflow:
Build an image containing our development environment. (Rails, Django...)
Start a container from that image.Use the v flag to mount source code inside the container .
Edit source code outside the containers, using regular tools.(vim, emacs, textmate...)
Test application.(Some frameworks pick up changes automatically.Others require you to CtrlC +
restart after each modification.)
Repeat last two steps until satisfied.
When done, commit+push source code changes. (You are using version control, right?)
Debugging inside the container
Docker introduced a feature called docker exec.
It allows users to run a new process in a container which is already running.If sometimes you find
yourself wishing you could SSH into a container: you can use docker exec instead.You can get a shell
prompt inside an existing container this way, or run an arbitrary process for automation.
docker exec example
$ # You can run ruby commands in the area the app is running and more!
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
$ docker exec -it <yourContainerId> bash
root@5ca27cf74c2e:/opt/namer# irb
irb(main):001:0> [0, 1, 2, 3, 4].map {|x| x ** 2}.compact => [0, 1, 4, 9, 16]
irb(main):002:0> exit
Stopping the container
Now that we're done let's stop our container.
$ docker stop <yourContainerID>
And remove it
$ docker rm ourContainerID>
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
14. Using Docker Compose for Development Stacks
Dockerfiles are great to build a single container. But when you want to start a complex stack made of
multiple containers, you need a different tool. This tool is Docker Compose.
In this lesson, you will use Compose to bootstrap a development environment.
Compose for Development Stacks
What is Docker Compose?
Docker Compose (formerly known as fig) is an external tool. It is optional (you do not need Compose to
run Docker and containers) but we recommend it highly! The general idea of Compose is to enable a very
simple, powerful onboarding workflow:
• Clone your code.
• Run docker-compose up.
• Your app is up and running!
Compose overview
This is how you work with Compose:
You describe a set (or stack) of containers in a YAML file called docker-compose.yml.
You run docker-compose up.
Compose automatically pulls images, builds containers, and starts them.
Compose can set up links, volumes, and other Docker options for you.
Compose can run the containers in the background, or in the foreground.
When containers are running in the foreground, their aggregated output is shown.
Checking if Compose is installed
If you are using the official training virtual machines, Compose has been pre-installed.
You can always check that it is installed by running:
$ docker-compose --version
Installing Compose
If you want to install Compose on your machine, there are (at least) two methods.
Compose is written in Python. If you have pip and use it to manage other Python packages, you can
install compose with:
$ sudo pip install docker-compose
(Note: if you are familiar with virtualenv, you can also use it to install Compose.)
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
If you do not have pip, or do not want to use it to install Compose, you can also retrieve an all-in-one
binary file:
curl -L \
https://github.com/docker/compose/releases/download/1.8.0/docker-
compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
$ chmod +x /usr/local/bin/docker-compose
Launching Our First Stack with Compose
First step: clone the source code for the app we will be working on.
$ cd
$ git clone git://github.com/jpetazzo/trainingwheels
...
$ cd trainingwheels
Second step: start your app.
$ docker-compose up
Watch Compose build and run your app with the correct parameters, including linking the relevant
containers together.
Launching Our First Stack with Compose
Verify that the app is running at http://<yourHostIP>:8000.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Stopping the app
When you hit ^C, Compose tries to gracefully terminate all of the containers. After ten seconds (or if you
press ^C again) it will forcibly kill them.
The docker-compose.yml file
Here is the file used in the demo:
version: "2"
services:
www:
build: www
ports:
- 8000:5000
user: nobody
environment:
DEBUG: 1
command: python counter.py
volumes:
- ./www:/src
redis:
image: redis
Compose file versions
Version 1 directly has the various containers (www, redis...) at the top level of the file.
Version 2 has multiple sections:
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
➢ version is mandatory and should be "2".
➢ services are mandatory and corresponds to the content of the version 1 format.
➢ networks are optional and can define multiple networks on which containers can be placed.
➢ volumes are optional and can define volumes to be used (and potentially shared) by the
containers.
Containers in docker-compose.yml
Each service in the YAML file must contain either build, or image.
build indicates a path containing a Dockerfile.
image indicates an image name (local, or on a registry).
The other parameters are optional.
They encode the parameters that you would typically add to docker run. Sometimes they have several
minor improvements.
Container parameters
• command indicates what to run (like CMD in a Dockerfile).
• ports translate to one (or multiple) -p options to map ports. You can specify
local ports (i.e. x:y to expose public port x).
• volumes translates to one (or multiple) -v options.
You can use relative paths here.
For the full list, check http://docs.docker.com/compose/yml/.
Compose commands
We already saw docker-compose up, but another one is docker-compose build. It will execute docker
build for all containers mentioning a build path. It is common to execute the build and run steps in
sequence:
$ docker-compose build && docker-compose up
Another common option is to start containers in the background:
$ docker-compose up –d
Check container status
It can be tedious to check the status of your containers with docker ps, especially when running multiple
apps at the same time.
Compose makes it easier; with docker-compose ps you will see only the status of the containers of the
current stack:
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------
trainingwheels_redis_1 docker-entrypoint.sh redis ... Up 6379/tcp
trainingwheels_www_1 python counter.py Up 0.0.0.0:8000->5000/tcp
Cleaning up
If you have started your application in the background with Compose and want to stop it easily, you can
use the kill command:
$ docker-compose kill
Likewise, docker-compose rm will let you remove containers (after confirmation):
$ docker-compose rm
Going to remove trainingwheels_redis_1, trainingwheels_www_1
Are you sure? [yN] y
Removing trainingwheels_redis_1...
Removing trainingwheels_www_1...
Alternatively, docker-compose down will stop and remove containers.
$ docker-compose down
Stopping trainingwheels_www_1 ... done
Stopping trainingwheels_redis_1
... done Removing trainingwheels_www_1 ... done Removing
trainingwheels_redis_1
... done
Special handling of volumes
Compose is smart. If your container uses volumes, when you restart your application,
Compose will create a new container, but carefully re-use the volumes it was using previously.
This makes it easy to upgrade a stateful service, by pulling its new image and just restarting your
stack with Compose.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.
Visualpath Training & Consulting.
Flat no: 205, Nilgiri Block,Aditya Enclave, Ameerpet, Hyderabad, Phone No: - +91-970 445 5959, 961 824 5689 E-
Mail ID : online.visualpath@gmail.com, Website : www.visualpath.in.