Docker for Sysadmins: Linux Windows VMware

Docker for Sysadmins: Linux Windows VMware
Docker for Sysadmins: Linux Windows VMware
Buy on Leanpub

0: About the book

This is a book about Docker, hand-crafted for system administrators. No prior knowledge required!

But what about developers and DevOps?

If you’re a developer with no interest in operations then this book is not for you. If you’re into DevOps then you’ll get a lot from the book.

To keep things short… the book is not about showing you how to develop microservice apps with Docker. The book is about how Docker works. You’ll learn the how and the why - the commands and the theory. I really want to set you on your way to being as good at Docker as you already are at Linux, Windows or VMware.

Why should I read this book or care about Docker?

Docker is coming and there’s no hiding from it. Developers are all over it. In IT Ops, we need to get ready to support Dockerized apps in our business critical production environments.

Isn’t Docker just for developers?

If you think the answer to that is Yes, then you need a good slap!

All of those Dockerized apps that developers are creating need a solid Docker infrastructure to run on. And that’s where Ops comes into the picture… Ops will need to build and run high performance and highly available Docker infrastructures. If we’re not skilled-up on Docker, we’re going to struggle.

Why this Docker book and not one of the others?

At the time I decided to write the first edition of this book, so many of the Docker books already out there were terrible! Many of them were badly written, full of technical inaccuracies, or massively out of date. And sometimes they were all three! It’s honestly not my intention to offend people, but go and read some of the reviews on Amazon. Some of the Docker books out there are a shameful waste of trees and paper!

So I decided to write something that was well written, technically accurate, and kept up to date. I don’t want you to buy this book and put it on the shelf. I want you to love this book!

If you buy the book and think it’s bad, call me out on Twitter, give the book bad reviews, do whatever you feel necessary. And I’ll try and fix it. But I’m confident you won’t need to do any of that.

Should I buy the book if I’ve already watched your video courses?

If you like my video courses you’ll probably like the book. If you don’t like my video courses you probably won’t like the book.

How the book is organized

I’ve divided the book into two sections:

  • The general info stuff
  • The technical stuff

The general info stuff covers things like - Who is Docker, Inc. What is the Docker project. What is the OCI. Why do we even have containers… Not the coolest part of the book, but the kind of stuff that’s important if you want a good rounded knowledge of Docker and containers. It’s only a short section and you should probably read it.

The technical stuff is what the book is all about! This is where you’ll find everything you need to start working with Docker. It gets into the detail of images, containers and the increasingly important topic of orchestration. You’ll get the theory so that you know how it all fits together, and you’ll get commands and examples to show you how it all works in practice.

Every chapter in the technical stuff section is divided into three parts:

  • The TLDR
  • The deep dive
  • The commands

The TLDR will give you two or three paragraphs that you could use to explain the topic at the coffee machine. They’re probably good as quick reminders if you get lost in the details.

TLDR or TL;DR, is a modern acronym meaning “too long; didn’t read”. It’s normally used to indicate something that was too long to bother reading. I’m using it here in the book to indicate a short section that you can read if you’re in a hurry and haven’t got time to read the longer deep dive that immediately follows it.

The deep dive is where we’ll explain how everything works and go through the examples.

The Commands lists out all of the relevant commands in an easy to read list with brief reminders of what each one does.

I think you’ll love that format.

Other stuff about the book

Here are just a few other things I want you to know about the book.

Text wrapping

I’ve tried really hard to get the commands and outputs to fit on a single line without wrapping! So instead of getting this…

$ docker service ps uber-service
ID                         NAME                 IMAGE                    NOD\
E              DESIRED STATE  CURRENT STATE               ERROR
7zi85ypj7t6kjdkevreswknys  uber-service.1       nigelpoulton/tu-demo:v2  ip-\
172-31-12-203  Running        Running about an hour ago
0v5a97xatho0dd4x5fwth87e5   \_ uber-service.1   nigelpoulton/tu-demo:v1  ip-\
172-31-12-207  Shutdown       Shutdown about an hour ago
31xx0df6je8aqmkjqn8w1q9cf  uber-service.2       nigelpoulton/tu-demo:v2  ip-\
172-31-12-203  Running        Running about an hour ago

… you should get this.

$ docker service ps web-fe
ID          NAME      IMAGE             NODE  DESIRED  CURRENT
817f...f6z  web-fe.1  nigelpoulton/...  mgr2  Running  Running 5 mins
a1dh...mzn  web-fe.2  nigelpoulton/...  wrk1  Running  Running 5 mins
cc0j...ar0  web-fe.3  nigelpoulton/...  wrk2  Running  Running 5 mins

For best results you might want to flip your reading device into landscape mode.

In doing this I’ve had to trim some of the output from some commands, but I don’t think you’re missing anything important. However, despite all of this, if you’re reading on a small enough device, you’re still going to get some wrapping :-(

But you didn’t include something I really hoped you would…

I know the book doesn’t cover everything about Docker. But it’s not supposed to! I’ve written the book to get you up to speed as quickly as possible while still spending the time to learn how it all fits together. If the book was 1,000 printed pages it would not help you get up to speed quickly!

However, I will add sections to the book if I think they’re important enough. Please use the book’s feedback pages and hit me up on Twitter with ideas of what you think should be included in the next version of the book.

Right, that’s enough waffling. Let’s crack on!

4: The big picture

In the next few chapters we’re going to get into the details of things like images, containers, and orchestration. But before we do that, it’s a good idea to show you the big picture.

In this chapter we’ll download an image, start a new container, log in to the new container, run a command inside of it, and then destroy it. This will give you a good idea of what Docker is all about and how some of the major components fit together.

But don’t worry if some of the stuff we do here is totally new to you. We’re not trying to make you experts by the end of this chapter. All we’re doing here is giving you a feel of things - setting you up so that when we get into the details in later chapters, you have an idea of how the pieces fit together.

All you need to follow along with the exercises in this chapter is a single Docker host. This can be any of the options we just installed in the previous chapter. It doesn’t matter if this Docker host is a VM on your laptop, an instance in the public cloud, or bare metal server in your data center. All it needs, is to be running Docker with a connection to the internet. We’ll be showing examples using Linux and Windows!

Engine check

When you install Docker you get two major components:

  • the Docker client
  • the Docker daemon (sometimes called server)

The daemon implements the Docker Remote API.

In a default Linux installation the client talks to the daemon via a local IPC/Unix socket at /var/run/docker.sock. On Windows it listens on a named pipe at npipe:////./pipe/docker_engine. You can test that the client and daemon are operating and can talk to each other with the docker version command.

$ docker version
 Version:      17.05.0-ce
 API version:  1.29
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:10:54 2017
 OS/Arch:      linux/amd64

 Version:      17.05.0-ce
 API version:  1.29 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   89658be
 Built:        Thu May  4 22:10:54 2017
 OS/Arch:      linux/amd64
 Experimental: false

As long as you get a response back from the Client and Server components you should be good to go. If you are using Linux and get an error response from the Server component, try the command again with sudo in front of it: sudo docker version. If it works with sudo you will need to prefix the remainder of the commands in this chapter with sudo.


Now let’s look at images.

Right now, the best way to think of a Docker image is as an object that contains an OS filesystem and an application. It’s not massively different from a virtual machine template. A virtual machine template is essentially a stopped virtual machine. In the Docker world, an image is effectively a stopped container.

Run the docker image ls command on your Docker host.

$ docker image ls

If you are working from a freshly installed Docker host it will have no images and will look like the output above.

Getting images onto your Docker host is called “pulling”. If you are following along with Linux ,pull the ubuntu:latest. If you are following along on Windows, pull the microsoft/powershell:nanoserver image.

$ docker image pull ubuntu:latest
latest: Pulling from library/ubuntu
b6f892c0043b: Pull complete
55010f332b04: Pull complete
2955fb827c94: Pull complete
3deef3fcbd30: Pull complete
cf9722e506aa: Pull complete
Digest: sha256:382452f82a8b....463c62a9848133ecb1aa8
Status: Downloaded newer image for ubuntu:latest

Run the docker image ls command again to see the image you just pulled.

$ docker images
ubuntu          latest   bd3d4369aebc    11 days ago     126.6 MB

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 an image 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 filesystem including a few of the common Ubuntu utilities. The microsoft/powershell image pulled in the Windows example contains a Windows Nano Server OS with PowerShell.

It’s also worth noting that each image gets it’s own unique ID. When working with the images you can refer to them using either IDs or names.


Now that we have an image pulled locally on our Docker host, we can use the docker container run command to launch a container from it.

For Linux:

$ docker container run -it ubuntu:latest /bin/bash

For Windows:

> docker container run -it microsoft/powershell:nanoserver PowerShell.exe
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\>

Look closely at the output from the commands 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 container run command. docker container 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 terminal to the shell of the container (we’ll get more specific about this in the chapter on containers). Next, the command tells Docker that we want the container to be based on the ubuntu:latest image (or the microsoft/powershell:nanoserver image if you’re following along with Windows). Finally, we tell Docker which process we want to run inside of the container. For the Linux example we’re running a Bash shell, for the Windows container were running PowerShell.

Run a ps command from inside of the container to list all running processes.

Linux example:

root@6dc20d508db0:/# ps -elf
4 S root     1     0    0 -  4560 wait   13:38 ?    00:00:00 /bin/bash
0 R root     9     1    0 -  8606 -      13:38 ?    00:00:00 ps -elf

Windows example:

PS C:\> ps

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
      0       5      964       1292       0.00   4716   4 CExecSvc
      0       5      592        956       0.00   4524   4 csrss
      0       0        0          4                 0   0 Idle
      0      18     3984       8624       0.13    700   4 lsass
      0      52    26624      19400       1.64   2100   4 powershell
      0      38    28324      49616       1.69   4464   4 powershell
      0       8     1488       3032       0.06   2488   4 services
      0       2      288        504       0.00   4508   0 smss
      0       8     1600       3004       0.03    908   4 svchost
      0      12     1492       3504       0.06   4572   4 svchost
      0      15    20284      23428       5.64   4628   4 svchost
      0      15     3704       7536       0.09   4688   4 svchost
      0      28     5708       6588       0.45   4712   4 svchost
      0      10     2028       4736       0.03   4840   4 svchost
      0      11     5364       4824       0.08   4928   4 svchost
      0       0      128        136      37.02      4   0 System
      0       7      920       1832       0.02   3752   4 wininit
      0       8     5472      11124       0.77   5568   4 WmiPrvSE

Inside the Linux container there are only two processes running:

  • PID 1. This is the /bin/bash process that we told the container to run with the docker container run command.
  • PID 9. This is the ps -elf command/process that we ran to list the running processes.

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.

The Windows container has a lot more internal processes running. This is an artifact of the way the Windows Operating System works. Although it is a lot more processes than the Linux container, it is still a lot less processes than are running on the Windows Server host.

Press Ctrl-PQ to exit the container without terminating it. This will land you back in the shell of your Docker host. You can verify this by looking at your shell prompt.

Now that you are back at the shell prompt of you Docker host, run the ps command again.

Linux example:

$ ps -elf
4 S root         1     0     0 -  9407 -      00:00:03 /sbin/init
1 S root         2     0     0 -     0 -      00:00:00 [kthreadd]
1 S root         3     2     0 -     0 -      00:00:00 [ksoftirqd/0]
1 S root         5     2   -20 -     0 -      00:00:00 [kworker/0:0H]
1 S root         7     2     0 -     0 -      00:00:00 [rcu_sched]
0 R ubuntu   22783 22475     0 -  9021 -      00:00:00 ps -elf

Windows example:

> ps
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    220      11     7396       7872       0.33   1732   0 amazon-ssm-agen
     84       5      908       2096       0.00   2428   3 CExecSvc
     87       5      936       1336       0.00   4716   4 CExecSvc
    203      13     3600      13132       2.53   3192   2 conhost
    210      13     3768      22948       0.08   5260   2 conhost
    257      11     1808        992       0.64    524   0 csrss
    116       8     1348        580       0.08    592   1 csrss
     85       5      532       1136       0.23   2440   3 csrss
    242      11     1848        952       0.42   2708   2 csrss
     95       5      592        980       0.00   4524   4 csrss
    137       9     7784       6776       0.05   5080   2 docker
    401      17    22744      14016      28.59   1748   0 dockerd
    307      18    13344       1628       0.17    936   1 dwm
   1888       0      128        136      37.17      4   0 System
    272      15     3372       2452       0.23   3340   2 TabTip
     72       7     1184          8       0.00   3400   2 TabTip32
    244      16     2676       3148       0.06   1880   2 taskhostw
    142       7     6172       6680       0.78   4952   3 WmiPrvSE
    148       8     5620      11028       0.77   5568   4 WmiPrvSE

Notice how many more processes are running on your Docker host compared to the long-running process inside of the container.

In a previous step you pressed Ctrl-PQ to exit from the container. Doing this from inside of a container will exit you from the container without killing it. You can see all of the running containers on your system using the docker container ls command.

$ docker container ls
e2b69eeb55cb   ubuntu:latest  "/bin/bash"   7 mins   Up 7 min  vigilant_borg

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 7 minutes ago and has been running for 7 minutes.

Attaching to running containers

You can attach your shell to running containers with the docker container exec command. As the container from the previous steps is still running let’s connect back to it.

Linux example:

This example references a container called “vigilant_borg”. The name of your container will be different, so remember to substitute “vigilant_borg” with the name or ID of the container running on your Docker host.

$ docker container exec -it vigilant_borg bash

Windows example:

This example references a container called “pensive_hamilton”. The name of your container will be different, so remember to substitute “pensive_hamilton” with the name or ID of the container running on your Docker host.

> docker container exec -it pensive_hamilton PowerShell.exe
Windows PowerShell
Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\>

Notice that your shell prompt has changed again. You are back inside the container.

The format of the docker container exec command is: docker container 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 (PowerShell in the Windows example). We could easily have referenced the container by its ID.

Exit the container again by pressing Ctrl-PQ.

Your shell prompt should be back to your Docker host.

Run the docker container ls command again to verify that your container is still running.

$ docker container ls
e2b69eeb55cb   ubuntu:latest  "/bin/bash"   9 mins   Up 9 min  vigilant_borg

Stop the container and kill it using the docker container stop and docker container rm commands. Remember to substitute the names/IDs of your own containers.

$ docker container stop vigilant_borg
$ docker container rm vigilant_borg

Verify that the container was successfully deleted by running another docker container ls command.

$ docker container ls

Congratulations! You’ve downloaded a Docker image, launched a container from that image, executed a command inside of the container (ps) and then stopped and deleted the container. This big picture view should help you with the up-coming chapters where we will dig deeper into images and containers.