Red Green Repeat Adventures of a Spec Driven Junkie

Docker Essentials

Docker has been on my radar for a long time. After learning virtualboxes, vagrant, puppet, I now want to step into the docker world more.

Each time I have been working with docker, I keep looking up the same information, so this article is a reference and a comprehensive explanation for these items.

Virtual Machine vs. Docker

Initially, I didn’t really understand the difference between using virtual machines and docker.

When running a single app, the difference between running the app on virtual machine or on docker is minimal.

The difference becomes more apparent when running apps on a single host computer. For greatest isolation, having each app running in its own operating system is ideal.

To reach this ideal using virtual machines, the amount of resources used per app increases, especially with more guest operating systems.

virtual machine and docker comparison

Each app on docker does not need its own guest operating system when running an app, so the host system has more resources available for apps.

Installing Docker

Installation instructions have change over time, the most current method to install docker is to look at their install page

I am focusing on Community Edition for this article.

macOS

Install docker from the AppStore or using this link from the docker store. The docker client for macOS has great integration, even using Apple’s HyperKit on newer macOS, so a separate virtual machine is not required anymore.

Ubuntu

Remove Previous Installs

$ sudo apt-get remove docker docker-engine docker.io

Docker has changed frequently over the last five years, so removing any old versions will avoid any weird undocumented errors.

Add Repository

$ sudo add-apt-repository "deb [arch=amd64]
https://download.docker.com/linux/ubuntu
$(lsb_release -cs) stable"

Install Docker

$ sudo apt-get update; sudo apt-get install -y docker-ce

The application is docker but the apt package name is: docker-ce.

source

Key Concepts

I have found the two base concept to docker are images and containers. Once I understood these two concepts, I had an easier time working with docker in general.

Images

Are binary builds of a system. This image file can be an operating system, or an application such as a webserver.

A file or interactively creation of the image is possible. One can also download images created by others from repositories, such as https://hub.docker.com

Containers

To run an image, a virtualized environment supports the computing resource needs of the image, such as accessing the processor and memory.

One can run a single image on multiple containers on the same computer with different options. (i.e. the same webserver on different ports)

SHA-256

SHA-256, SHA-256 EVERYWHERE

The Secure Hash Algorithm used different places in docker:

  • An image is uniqely identified and versioned by a SHA-256 value.
  • Every running container is addressable by a SHA-256 value.

Docker commands can always operate on a SHA-256 value. Just use the proper value, the image or container, for the command. I

Images

These are binary application files that run in different containers. This section covers two important docker commands are: listing and getting images.

Listing Images

To list images that are on the host system, run:

$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 2a4cca5ac898 3 days ago 111MB

This will list all downloaded or stored images on the current system.

If there are no images on the system, it will display:

$ docker images
REPOSITORY TAG IMAGE ID CREATED

image_id

An image is addressable by its name (i.e. ubuntu for the ubuntu image) or its SHA-256 value - 2a4cca5ac898 as of this writing.

For the rest of this article, I will use image_id to refer to either an image’s name or SHA-256 value.

Getting Images

To get images from docker hub, use the docker pull command:

$ docker pull <image_id>

to grab the ubuntu image, the command is:

$ docker pull ubuntu

Containers

Running an image puts it in a container.

Listing Containers

To find out what containers are running on your system, run:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b8996065500e ubuntu "/bin/bash" 4 seconds ago Up 2 seconds clever_goldstine

The output lists all the running containers on the system along with the image the container uses.

container_id

Like an image, a container is referencable by its SHA-256 listed in the container ID section of docker ps, or the name of the image running the container.

For the rest of this article, I will use container_id to refer to either an container’s name or SHA-256 value.

Running Images in Containers

To run a specific image, run command:

$ docker run <image_id>

This will start a container with the specified image.

Container Options

The container options I have to be essential so far are: ports and volumes.

ports

One way to connect to the running container is through the port the running application uses, like port 80 for a webserver.

When specifying a port on docker run, this exposes the port of the container to the host, allowing the host to connect to the container.

$ docker run -p <host port>:<container port> <image_id>

So, if a webserver is running in a container, the port it is using is port 80. To be able to access the webserver from the host computer, pass in option:

$ docker run -p 8080:80 <image_id>

In a web browser, enter address: http://localhost:8080 to access the web server of the container.

volumes

Setting the volume option links files from the host computer (i.e. the current directory) to the container.

$ docker run -v <host directory>:<guest directory> <image_id>

So, to mount local files for the webserver:

$ docker run -v _site:/usr/share/nginx/html -p 8080:80 nginx

To see the served files in a web browser, enter address: http://localhost:8080.

Interacting with Containers

It is possible to login to a running container and interact with it like a virtualbox system. This can be handy to debug or to figure out the configuration of the docker image.

Logging in

To connect to the container through SSH, the command is:

$ docker exec -it <container_id> <command>

Most of the time, the command option will be bash, the default shell on most unix systems.

I have run into situations where bash was not installed, and had to use sh.

To find out what shells are in the container, run:

$ docker export CONTAINER|tar -t|egrep ^bin/

source

Shutting Down

I have found three ways to topping a container: ^C, docker stop and sudo htop. Each are useful depending on the situation.

^C

docker running in
terminal

This is easiest if the terminal running the container is still accesible. Docker will receive the SIGTERM and stop.

docker stop

If the running container terminal cannot be easily accessed, using the command:

$ docker stop <container_id>

will stop the running container as well. One can obtain the container ID from the docker ps command.

sudo htop

htop killing
process

A final resort to stopping a container, even when docker stop does not work, is to use htop, but running the process with root privileges. docker stop may not stop a stuck container.

Using sudo htop instead allows for easy identification of the process from the htop interface and to stop with different levels, like SIGKILL.

Conclusion

This is a quick overview of the essentials of working with docker: images, containers, starting, and stopping.

Docker seems to be a basic technology to virtualize software, but when looking further, I see it as a powerful tool to run and manage apps. Technology that helps with this excites me.

I’m looking forward to working with docker more.